设计模式之结构型模式
设计模式分为三大类:
(1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
(2)结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
(3)行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
适配器模式(Adapter Pattern)--把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。
优点:
- 更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。 - 解耦性
将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码 - 符合开放-关闭原则
同一个适配器可以把适配者类和它的子类都适配到目标接口;可以为不同的目标接口实现不同的适配器,而不需要修改待适配类
装饰器模式(Decorator) -- 对已经存在的某些类进行装饰,以此来扩展一些功能
优点:
- 装饰类和被装饰类可以独立发展,不会相互耦合.
- 装饰模式是继承的一个替代模式,但是他提供了比继承更多的灵活性.
- 装饰模式可以动态的方式扩展一个实现类的功能.在运行时选择不同的装饰器,从而实现不同的行为
缺点:
- 多层装饰比较复杂
代理模式(Proxy Pattern)--通过引入代理对象的方式来间接访问目标对象
优点:
- 协调调用者和被调用者,降低了系统的耦合度
- 代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用
缺点:
- 由于在客户端和真实主题之间增加了代理对象,因此会造成请求的处理速度变慢;
- 实现代理模式需要额外的工作(有些代理模式的实现非常复杂),从而增加了系统实现的复杂度。
外观模式(Facade Pattern)
- 引入外观角色之后,用户只需要与外观角色交互;
- 用户与子系统之间的复杂逻辑关系由外观角色来实现
优点:
- 降低了客户类与子系统类的耦合度,实现了子系统与客户之间的松耦合关系
- 外观模式对客户屏蔽了子系统组件,从而简化了接口
缺点:
- 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”
桥接模式(Bridge)--把抽象化与实现化解耦,使得二者可以独立变化
优点:
- 实现了抽象和实现部分的分离
- 更好的可扩展性
缺点:
- 桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程。
- 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。
组合模式(Composite)--通过引入一个抽象的组件对象,作为组合对象和叶子对象的父对象,这样就把组合对象和叶子对象统一起来了,用户使用的时候,始终是在操作组件对象,而不再去区分是在操作组合对象还是在操作叶子对象
优点:
- 定义了包含基本对象和组合对象的类层次结构,统一了组合对象和叶子对象
- 简化了客户端调用
组合模式的本质:统一叶子对象和组合对象。
享元模式(Flyweight Pattern)--运用共享技术有效地支持大量细粒度对象的复用
广义上讲,在JDK类库中定义的String类也是使用享元模式的典型。
适用场景:
- 一个系统有大量相同或者相似的对象,由于这类对象的大量使用,造成内存的大量耗费
- 使用享元模式需要维护一个存储享元对象的享元池,而这需要耗费资源,因此,应当在多次重复使用享元对象时才值得使用享元模式。
优点:
- 极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份;
- 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
缺点:
- 享元模式使得系统更加复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化;
- 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。