设计模式

前言

Linus Benedict Torvalds : RTFSC – Read The Funning Source Code

面向对象六原则

所有的设计模式都是基于一个准则来衡定的,这个准则总结起来就是面向对象六原则。

  • 开闭原则 : 软件实体应当对扩展开放,对修改关闭。
  • 单一职责原则 : 一个类应该仅有一个引起它变化的原因。
  • 里氏替换原则 : 子类可以替换父类并且出现在父类能够出现的任何地方。
  • 依赖倒置原则 : 高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
  • 接口隔离原则 : 使用多个专门的接口比使用单个接口要好的多。
  • 最少知识原则 : 一个对象应当对其他对象有尽可能少的了解。

设计模式

在理解设计模式前首先得认识下UML图的意思。

  1. 关联:
    在代码中的体现:成员变量
    设计模式-关联.png

  2. 继承:
    设计模式-继承.png

  3. 聚合:
    在代码中的体现:成员变量
    设计模式-聚合.png

  4. 实现:
    在代码中的体现:接口实现
    设计模式-实现.png

  5. 依赖:
    在代码中的体现:局部变量、方法的参数或者对静态方法的调用(关系弱)
    设计模式-依赖.png

  6. 组合:
    在代码中的体现:成员变量(关系强)
    设计模式-组合.png

单例模式

确保这个类只有一个实例,而且能自行实例化,当然要看是使用饱汉还是饥汉模式。

UML 图:
设计模式-单例模式.png

优点:减少内存、性能开销,避免资源重用,并且可以全局访问。
缺点:扩展很难,当持有 context 之类的对象容易造成内存泄漏。

单例模式 代码

Builder模式

将一个复杂对象的构建与表示分离,使同样的构建可以创建不同表示。

UML 图:
设计模式-Builder模式.png

优点:建立良好的封装,创建独立,容易扩展。
缺点:产生多余的builder对象以及director对象,消耗内存。

原型模式

原型模式实际上就是对象拷贝,分为浅拷贝和深拷贝。利用原型模式可以解决构建复杂对象的资源消耗问题。

Builder模式 代码

UML 图:
设计模式-原型模式.png

优点:在产生大量对象或者在创建对象时消耗时间过长的时候可以很好的优化性能。
缺点:在内存中拷贝的时候要小心浅拷贝和深拷贝,避免发生混乱。

工厂模式

定义一个用于创建对象的接口,让子类决定实例化哪个类。

UML 图:
设计模式-工厂模式.png

优点:为系统结构提供灵活的动态扩展机制.减速少工作量,方便维护。
缺点:每次添加新产品时都会引入一个抽象层,导致类结构的复杂化。

抽象工厂模式

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

UML 图:
设计模式-抽象工厂模式.png

优点:分离接口与实现,并且没有工厂模式的那么多冗余抽象类。
缺点:当然也有类文件过多的问题,不太容易扩展新产品类,每当增加新类就要改写接口,所有类都要重新修改一遍。

策略模式

定义一系列的算法,并将每个算法封装,使他们可以相互替换。

UML 图:
设计模式-策略模式.png

优点:结构清晰,耦合度低,封装彻底数据也更为安全。
缺点:子类会变得越来越繁多。

状态模式

当一个对象的内在状态改变时允许改变其行为。

UML 图:
设计模式-状态模式.png

优点:提供一种更好的方式来组织特定状态的代码,消除 if-else 的丑陋结构。
缺点:增加系统类和对象个数。

责任链模式

使多个对象都有机会处理请求,从而避免请求的发送这和接受者之间的耦合关系。将这些对象连成一条链,并沿着链传递请求直到处理为止。

UML 图:
设计模式-责任链模式.png

优点:可以对请求者和处理者关系解耦。
缺点:对链中的处理者遍历会消耗性能。

责任链模式 代码

解释器模式

给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。

UML 图:
设计模式-解释器模式.png

优点:解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。
缺点:因为每个解释都有一个解释类,那么就会像 PMS 那样对每个标签都要解析导致很多的类出现。

解释器模式 代码

命令模式

将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

UML 图:
设计模式-命令模式.png

优点:可以对代码进行强解耦,保持开闭原则。
缺点:类会变得很臃肿,要小心使用。

解释器模式 代码

观察者模式

定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

UML 图:
设计模式-观察者模式.png

优点
第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。
由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。
第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。

缺点
第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

观察者模式 代码

代理模式

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

UML 图:
设计模式-代理模式.png

优点
第一、代理模式能将代理对象与真正被调用的对象分离,在一定程度上降低了系统的耦合度。
第二、代理模式在客户端和目标对象之间起到一个中介作用,这样可以起到保护目标对象的作用。代理对象也可以对目标对象调用之前进行其他操作。

缺点
第一、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
第二、增加了系统的复杂度。

代理模式 代码