Design Mode note Adapter mode Adapter
// Adapter mode ---- Class Object Structure Mode
/*
1: Intention:
Converts an interface of a class to another interface that the customer wants. The Adapter mode makes the original interface incompatible
Those classes that cannot work together can work together.
2: alias: Wrapper
3: Motivation
4: Applicability:
1> you want to use an existing class, and its interface does not meet your needs.
2> you want to create a reusable class, which can be unrelated to other classes or unforeseen classes (that is, those interfaces)
Classes that may not be compatible.
3> (Object Adapter only) You want to use existing subclasses, but it is impossible to subclass each one.
To match their interfaces. The Object Adapter can adapt to its parent class interface.
5: structure:
1> class adapter:
Client --------> Target: Adaptee:
Request () SpecificRequest ()
|
-----------------------
|
Adapter:
Request ()
{SpecificRequest ()}
2> Object Adapter:
Client --------> Target:
Request ()
| -----> Adaptee:
| Adaptee | SpecificRequest ()
Adapter -----------
Request ()
{Adaptee-> SpecificRequest ()}
6: participants:
1> Target: defines the interfaces used by the Client in specific fields.
2> Client: Works with objects that comply with the Target interface.
3> Adaptee: defines an existing interface, which must be adapted.
4> Adapter: Adapt the Adaptee interface to the Target interface.
7: collaboration:
The Client calls some operations on the Adapter instance. The adapter then calls the Adaptee Operation to implement this request.
8: effect:
1> class adapter:
1) Use a specific Adapter class to match Adaptee and Target. The result is that when we want to match a class
And all its child classes, the class Adapter will not be competent.
2) the Adapter can redefine some behavior of Adaptee because the Adapter is a subclass of Adaptee.
3) Only one object is introduced, and no extra pointer is required to indirectly obtain Adaptee.
2> Object Adapter:
1) allow one Adapter and multiple Adaptee -- that is, Adaptee itself and all its subclasses (if any)
Work simultaneously. The Adapter can also add functions to all Adaptee at a time.
2) This makes it difficult to redefine Adaptee, which requires generating a subclass of Adaptee and making the Adapter reference
This subclass does not reference Adaptee itself.
3> other factors to consider:
1) matching degree of the Adapter. The amount of work that matches the Adaptee interface and Target interface.
May be different. The scope of work may be from simple interface conversion (for example, changing the operation name) to support completely different operations.
Set. The workload of the Adapter depends on the similarity between the Target interface and the Adaptee interface.
2) pluggable Adapter. When other classes use a class, the fewer assumptions are required, the class is more
Reusability. If you construct an interface match as a class, you do not need to assume that the interface visible to other classes is the same.
That is to say, interface matching allows us to add our own classes to some existing systems.
The interfaces of this class may be different.
3) use a two-way adapter to provide transparent operations. A potential problem with using adapters is that they are not transparent to all customers.
The adapted object is no longer compatible with the Adaptee interface, so it is not where all Adaptee objects can be used.
Can be used. The two-way adapter provides such transparency. You can view the data in different ways for two different customers.
Bidirectional adapters are especially useful when the same object is used.
9: Implementation:
Notes:
1> use c ++ to implement the adapter. When using c ++ to implement the Adapter class, the Adapter class should inherit the Target class in public mode.
And inherit the Adaptee class in private mode. Because the Adaptee interface is used only and does not need to be inherited.
2> pluggable Adapter. There are many ways to achieve this. There are three types.
1) First (all three implementations are required ):
Find a narrow API for Adaptee to adapt to the minimum set of operations. Because the narrow interface that contains fewer operations is relatively
Wide interfaces with more operations are easier to match.
2) implementation path:
A): use abstract operations. Narrow interfaces define the corresponding abstract operations, which are implemented by sub-classes.
B): use a proxy object. The Adapter can store a proxy in the customer class and call the proxy's abstract method.
Abstract methods to achieve adaptation.
C): parameterized adapter.
10: Sample Code :*/
// Class adapter:
// Target
Class Shape
{
Public:
Shape ();
Virtual void BoundingBox (Point & bottomLeft, Point & topRight) const;
Virtual Manipulator * CreateManipulator () const;
};
// Adaptee
Class TextView
{
Public:
TextView ();
Void GetOrigin (Coord & x, Coord & y) const;
Void GetExtent (Coord & width, Coord & height) const;
Virtual bool IsEmpty () const;
};
// The Adapter only needs to implement the Target interface, but must use the Adaptee Interface
Class TextShape: public Shape, private TextView
{
Public:
TextShape ();
Virtual void BoundingBox (Point & bottomLeft, Point & topRight) const;
Virtual bool IsEmpty () const;
Virtual Manipulator * CreateManipulator () const;
};
// Set the Coord interface type to the Point type
Void TextShape: BoundingBox (Point & bottomLeft, Point & topRight) const
{
Coord bottom, left, width, height;
GetOrigin (bottom, left );
GetExtent (width, height );
BottomLeft = Point (bottom, left );
TopRight = Point (bottom + height, left + width );
}
Bool TextShape: IsEmpty () const
{
Return TextView: IsEmpty ();
}
// You need to implement it by yourself. Adaptee does not have this function.
Manipulator * TextShape: CreateManipulator () const
{
Return new TextManipulater (this );
}
// Object Adapter. The operations are almost identical. You only need to change the operations inherited from adaptee
// _ Text
Class TextShape: public Shape
{
Public:
TextShape (TextView *);
Virtual void BoundingBox (Point & bottomLeft, Point & topRight) const;
Virtual bool IsEmpty () const;
Virtual Manipulator * CreateManipulator () const;
Private:
TextView * _ text;
};
TextShape: TextShape (TextView * t)
{
_ Text = t;
}
Void TextShape: BoundingBox (Point & bottomLeft, Point & topRight) const
{
Coord bottom, left, width, height;
_ Text-> GetOrigin (bottom, left );
_ Text-> GetExtent (width, height );
BottomLeft = Point (bottom, left );
TopRight = Point (bottom + height, left + width );
}
Manipulator * TextShape: CreateManipulator () const
{
Return new TextManipulater (this );
}
// Although the implementation of the Object Adapter is a little more complicated, it is more flexible and can use the subclass of adaptee.