Structural patterns are concerned with how classes and objects are composed to form larger structures.Structural class patterns use inheritance to compose interfaces or implementations.
I.Adapter:
Intent:Convert the interface of a class into another interface clients expert.Adapter lets classes work together that couldn’t otherwise because of imcompatible interfaces.
Applicability:Use the Adapter pattern when
*you want to use an existing class,and its interface does not match one you need.
*you want to create a reusable class that cooperates with unrelated or unforeseen classes,that is,classes that don’t necessarily have compatible interfaces.
*(object adapter only)you need to use several existing subclasses,but it’s impractical to adapt their interface by subclassing every one.An object adapter can adapt the interface of its parent class.
Structure:
Consequences:
Class and object adapters have different trade-offs.
A class adapter:
*adapts Adaptee to Target by committing to a concrete Adaptee class.As a consequence,a class adapter won’t work when we want to adapt a class and all its subclasses.
*lets Adapter override some of Adaptee’s behavior,since Adapter is a subclass of Adaptee.
*introduces only one object,and no additional pointer indirection is needed to get to the adaptee.
An object adapter:
*lets a single Adapter work with many Adaptees—that is,the Adaptee itself and all of its subclasses(if any).The Adapter can also add functionality to all Adaptees at once.
*makes it harder to override Adaptee behavior.It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself.
Here are other issues to consider when using the Adapter pattern:
*How much adapting does Adapter do?
*Pluggable adapters.
*Using two-way adapters to provide transparency.
Sample code://c++,this is not a program
class Shape{
//target
public:
virtual void BoundingBox(Point& bottomleft,Point& topRight)const;
}
virtual Manipulator* CreateManipulator()const;
};
class TextView{
//Adaptee
public:
TextView();
void GetOrigin(Coord& x,Coord& y)const;
void GetExtent(Coord& width,Coord& height)const;
virtual bool IsEmpty()const;
};
class TextShape:public Shape,(optional)private TextView{
//Adapter
public:
TextShape();
// 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;
GetOrigin(left,bottom);
GetExtent(width,height);
// _text->GetOrigin(left,bottom);
// _text->GetExtent(width,height);
bottomLeft=Point(left,bottom);
topRight=Point(left+width,bottom+height);
}
bool TextShape::IsEmpty()const{
return TextView::IsEmpty();
// return _text->IsEmpty();
}
Manipulator* TextShape::CreateManipulator()const{
return new TextManipulator(this);
}
Related Patterns:
Bridge has a structure similar to an object adapter,but Bridge has a different intent:It is meant to separate an interface from its implementation so that they can be varied easily and independently.An adapter is meant to change the interface of an existing object.
Decorator enhances another object without changing its interface.A decorator is thus more transparent to the application than an adapter is.As a consequence,Decorator supports recursive composition,which isn’t possible with pure adapters.
Proxy defines a representative or surrogate for another object and dose not change its interface.
II.Bridge
Intent:
Decouple an abstraction from its implementation so that the two can vary independently.
Applicability:Use the Bridge pattern when:
*you want to avoid a permanent binding between an abstraction and its implementation.
*both the abstractions and their implementations should be extensible by subclass ing.In this case,the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.
*changes in the implementation of an abstraction should have no impact on clients;that is,their code should not have to be recompiled.
*you want to share an implementation among multiple objects,and this fact should be hidden from the client.
Structure:
Consequences:
*Decoupling interface and implementation.
*Improved extensibility.
*Hiding implementation details from clients.
implementation:
*Only one Implementor.
*Creating the right Implementor object.
*Sharing implementors.
Handle& Handle::operator(const Handle& other)
{
other._body->Ref();
_body->Unref();
if(_body->RefCount()==0)
delete _body;
_body=other._body;
return *this;
}
*Using multiple inheritance.
Sample Code://C++,Not a program
class Window{
public:
Window(View* contents);
//requests handled by window
virtual void DrawContents();
virtual void Open();
virtual void Close();
virtual void Iconify();
virtual void Deiconify();
//requests forwarded to implementation
virtual void SetOrigin(const Point& at);
virtual void SetExtent(const Point& extent);
virtual void Raise();
virtual void Lower();
virtual void DrawLine(const Point&,const Point&);
virtual void DrawRect(const Point&,const Point&);
virtual void DrawPolygon(const Point[],int n);
virtual void DrawText(const char*,const Point&);
protected:
WindowImp* GetwindowImp();
View* GetView();
private:
WindowImp* _imp;
View* _contents;
};
class WindowImp{
public:
virtual void ImpTop()=0;
virtual void ImpBottom()=0;
virtual void ImpSetExtent(const Point&)=0;
virtual void ImpSetOrigin(const Point&)=0;
virtual void DeviceRect(Coord,Coord,Coord,Coord)=