结构型设计模式是从程序的结构上解决模块之间的耦合问题。结构型设计模式主要有如下7种模式:
适配器模式(Adapter)
适配器提供客户端(client)需要的接口,适配器(adapter)的作用就是把客户端的请求转化为对适配者(adaptee)的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适配器模式的模式动机。
适配器模式有4个角色:
- client:
- target:
- adapter:
- adaptee:
类adapter的结构:
代码实现过程:
class Target {
public:
virtual void Request();
}
class Adaptee {
public:
void SpecificRequest();
}
class Adapter : public class Target, private class Adaptee {
public:
void Request() {
SpecificRequest();
}
}
对象adapter的结构:
class Adaptee {
public:
void SpecificRequest();
}
class Target {
public:
virtual void Request();
public:
Adaptee* adaptee;
}
class Adapter : public class Target {
public:
Adapter(){ adaptee = new Adapter(); }
~Adapter() { delete adaptee; }
void Request() {
adaptee->SpecificRequest();
}
}
桥接模式(Bridge)
作用:将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化。
bridge结构:
Abstraction
定义抽象类的接口。维护一个指向 Implementor 类型对象的指针。
RefinedAbstraction
扩充由 Abstraction 定义的接口。
Implementor
定义实现类的接口,该接口不一定要与 Abstraction 接口完全一致,甚至可以完全不同。
Implementor 接口仅提供基本操作,Abstraction 则定义了基于这些基本操作的较高层次的操作。ConcreteImplementor
实现 Implementor 接口并定义它的具体实现。
在以下情况下可以使用 Bridge 模式:
- 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。比如需要在程序运行时刻实现部分应可以被选择或者切换。
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译.
- 你想对客户完全隐藏抽象的实现部分。
- 类的层次需要将一个对象分解成两个部分。
- 你想在多个对象间共享实现,但同时要求客户并不知道这一点。
代码实现:
class Abstraction {
public:
Abstraction(Implementor* implementor) {imp = implementor; }
virtual void Operation() {
imp->Operation();
}
private:
Implementor* imp;
}
class RefinedAbstraction : public class Abstraction {
public:
virtual void OtherOperation();
}
class Implementor {
public:
virtual void Operation();
}
class ConcreteImplementorA : public Implementor {
public:
void Operation();
}
class client {
public:
void Test () {
Implementor* imp = new ConcreateImplementorA();
Abstraction* abstracat = new Abstraction(imp);
abstract->Operation();
}
}
组合模式(Composite)
组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,Composite 使得用户对于单个对象和组合对象的使用具有一致性。
composite 模式结构图:
涉及角色:
- Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
- Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。
- Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
适用场景:
- 你想表示对象的部分-整体层次结构
- 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
装饰模式(Decorator)
作用: 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
构造图:
适用的场景:
- 需要扩展一个类的功能,或给一个类增加附加责任。
- 需要动态的给一个对象增加功能,这些功能可以再动态地撤销。
- 需要增加一些基本功能的排列组合而产生的非常大量的功能,从而使继承变得 不现实。
外观模式(Facade)
作用: 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
享元模式(Flyweight)
作用:运用共享技术有效地支持大量细粒度的对象。
内部状态intrinsic和外部状态extrinsic:
1)Flyweight模式中,最重要的是将对象分解成intrinsic和extrinsic两部分。
2)内部状态:在享元对象内部并且不会随环境改变而改变的共享部分,可以称为是享元对象的内部状态
3)外部状态:而随环境改变而改变的,取决于应用环境,或是实时数据,这些不可以共享的东西就是外部状态了。
4)内部状态和外部状态之间的区别:
在Flyweight模式应用中,通常修改的是外部状态属性,而内部状态属性一般都是用于参考或计算时引用。
Flyweight执行时所需的状态必定是内部的或外部的。内部状态存储于ConcreteFlyweight对象之中;而外部状态则由Client对象存储或计算。当用户调用Flyweight对象的操作时,将该状态传递给它。
代理模式(Proxy)
作用: 为其它对象提供一种代理以控制对这个对象的访问。