转自:http://blog.sina.com.cn/s/blog_604527460100htwj.html
1. 设计模式学习方法
很多人都说设计模式不好学,学了也不会用,其实我认为这是一种误区,学习设计模
不是特意去模仿,而是要明白为什么会有设计模式的诞生,设计模式它最根本的用处是什么,它要体现的是什么!
设计模式是为程序代码优化而诞生的,目的是设计出易维护、容易拓展、易复用、灵活性好的程序。设计模式体现是面向对象的三大思想:封装、继承和多态。因而如果学习的时候只是生拉硬踹,那你永远也达不到那无剑胜有剑的境界。
那么如何学习设计模式呢?只要是把握好原则,并将设计模式分类记忆,了解各自的用途和区别!
2. 设计模式七大原则
① 单一职责原则(SRP )
就一个类而言,应该仅有一个引起它的变化的原因。
② 开放封闭原则(OCP)
软件实体(类、模块、函数等等)应该可以扩展,但是不可以修改。
③ 里氏代换原则(LSP )
任何基类可以出现的地方,子类一定可以出现,即子类型必须能够替换它们的基类型。 里氏代换原则是对“开-闭”原则的补充。
实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
④ 依赖倒转原则(DIP)
高层次模块不应该依赖底层模块。两个都应该依赖抽象,而抽象不应该依赖细节,但细节要你应该依赖抽象。
⑤ 接口隔离原则(ISP )
使用多个专门的接口比使用单一的总接口总要好。换而言之,从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的。
⑥ 合成/ 聚合复用原则(CARP )
就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过向这些对象的委派达到复用已有功能的目的。
简而言之,要尽量使用合成/聚合(黑盒复用),尽量不要使用继承(白盒复用)。
⑦ 迪米特法则(LoD )
如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
3. 设计模式三大类型
① 创建模式
是对类的实例化过程的抽象化。一些系统在创建对象时,需要动态地决定怎样创建对象,创建哪些对象,以及如何组合和表示这些对象。创建模式描述了怎样构造和封装这些动态的决定。
创建模式分为类的创建模式和对象的创建模式两种。
a) 类的创建模式:类的创建模式使用继承关系,把类的创建延迟到子类,从而封装了客户端将得到哪些具体类的信息,并且隐藏了这些类的实例是如何创建和放在一起的。
b) 对象的创建模式:对象的创建模式则把对象的创建过程动态的委派给另一个对象,从而动态地决定客户端将得到哪些具体类的实例,以及这些类的实例是如何被创建和组合在一起的。
创建模式包括以下几种:简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、多例模式、建造模式、原型模式等。
② 结构模式
描述如何将类或者对象结合在一起形成更大的结构。结构模式描述两种不同的东西:类与类实例。
根据这一不同,结构模式可以分为类的结构模式和对象的结构模式两种。
a) 类的结构模式:类的结构模式使用集成来把类、接口等组合在一起,以形成更大的结构。当一个类从父类继承并实现某接口时,这个新的类就把父类的结构和接口的结构结合起来。类的结构模式是静态的。一个类的结构模式的典型例子,就是类形式的适配器模式。
b) 对象的结构模式:对象的结构模式描述怎样把各种不同类型的对象组合在一起,以实现新的功能的方法。对象的结构模式是动态的。
结构模式包括以下几种:适配器模式、组合模式、装饰模式、代理模式、亨元模式、门面模式 、桥接模式等。
③ 行为模式
是对在不同的对象之间划分责任和算法的抽象化。行为模式不仅仅是关于类和对象的,而且是关于它们之间的互相作用的。
行为模式分为类的行为模式和对象的行为模式两种。
a) 类的行为模式:类的行为使用集成关系在几个类之间分配行为。
b) 对象的行为模式:对象的行为模式则使用对象的聚合来分配行为。
行为模式包括以下几种:策略模式、模板方法模式、观察者模式、迭代器模式、职责链模式、命令模式、备忘录模式、状态模式、访问者模式、解释器模式、中介者模式等。
4. 常用的几种模式
① 简单工厂模式
定义 :提供一个创建新类的接口。
个人小结 :将客户类与工厂类分开,消费者任何时候需要某种产品,只需向工厂请求即可。客户类无须修改就可以接纳新产品。
② 工厂模式
定义: 定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。
个人小结 :核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节,从而实现动态创建子工厂的作用,增加新产品生产线。
③ 抽象工厂模式
定义 :提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
个人小结 :工厂方法模式的一个进化版本,工厂方法模式更针对的是单一产品系列,而抽象工厂则针对的是多产品系列。
④ 策略模式
定义: 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的用户。
个人小结 :将算法家族分别封装并且和客户端分离,由客户端依据不同条件选择具体算法类,从而达到算法的动态替换,以及避免了算法类的增减对客户端的影响。
⑤ 装饰模式
定义: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
个人小结 :能够实现对功能类的动态改变和添加。如果功能类不完善,通过增加一个子类,可以很方便在原功能类之前或者之后去扩展它,如果原功能类最初设计不完善,我们还可以通过子类去重写原功能类,并替换原功能类,因此该模式对后期软件功能扩展维护很便利。
⑥ 适配器模式
定义: 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
个人小结 :此模式其实是提供一个转换的中介,来适应不同的功能需求。适配器模式一般在软件开发中不提倡用,它多用于软件维护期间的功能扩展或者版本更新。从扩展功能来说它与装饰模式有着区别,详细请见下文。
⑦ 观察者模式
定义: 定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对对象,使它们能够自动更新自己。
个人小结 :该模式提供了一对多的依赖关系,让多个观察者能同时监听某一个主题对象(通知者)。这个主题对象在状态上发生变化时,会通知所有被通知到的观察者对象(通知者随意增减被通知到的观察者),使他们能够自动更新自己。
⑧ 外观模式
定义: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
个人小结 :太常用了,就不多说了。主要用途就是将一个复杂的系统分为几个子系统。
⑨ 单例模式
定义: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
个人小结 :此模式在web开发上的用途最明显。当一个类只能有一个实例化存在,且可以在全局访问时使用此模式。比如说重复实例化(不能及时 回收),不仅会浪费系统资源,而且会使程序的运行效率下降,还有可能产生死循环或者异常错误(比如多线程,同时实例化多次该类会导致崩溃)。应用:数据库 连接、打印机、web开发等等。
⑩ 原型模式
定义: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
a) 浅复制
b) 深复制
个人小结 :此模式实现了代码复用,并且克隆时不必重新初始化新对象,而是动态获得对象运行使得状态,从而能在原克隆对象的基础上根据需要修 改,即实现“选择性粘贴”,最终提高了系统的缜密与性能。此模式有浅复制和深复制之分,两者的主要区别在于:浅复制是仅针对 ConcretePrototype类中值类型的字段,而深复制可以连ConcretePrototype类中引用的所有其他类进行复制,我们根据需要去 选择用哪种方式。
5. 对比与总结
① 简单工厂模式、工厂方法模式、抽象工厂模式
简单工厂属于类创建模式,抽象工厂属于对象创建模式,而工厂方法则介于类创建模式和对象创建模式之间。如我先前所说,工厂方法和抽象工厂其实本质上是一样 的(见个人小结),将对具体对象的创建委派给了子工厂,核心工厂不再涉及具体的创建。简单工厂在添加新功能时,要对核心工厂做更改,而工厂方法和抽象工厂 只需添加新的子工厂即可。但是他们三者共同的缺点也正是在添加功能上,都需要添加多个类和做一定的改动(简单工厂和抽象工厂更明显)。
② 策略模式与简单工厂
两者结构图十分相似,两者的思路完全一致,只不过抽象类表达以及客户端实现上稍有不同,两者抽象类不同之处是简单工厂有自身的逻辑判断,可根据不同需要来动态选择子类,而策略模式只能是需要谁直接用谁,换句话说简单工厂是间接去选择,而策略模式是直接去选择。
③ 装饰模式与适配器模式
两者都是主要用于对功能类进行扩展(别名叫包装模式)。区别在于装饰模式一般是在原功能类的基础上去进行扩充,而适配器是新增功能类与其他功能类结构可能 有很明显的不同。举个例子:某书店卖关于道德经的书,有4个版本;分别是完整版、精简版、英文版、日文版,其中完整版和精简版就是装饰模式;英文版和日文 版就是适配器模式。因为完整版和精简版内容是有一定相同的;而英文版和日文版的内容和原版就很可能不同,有文化差异嘛,会有一些思维逻辑的变化的。
适配器的用途还分为两种情况:一种为适应不同的接口,另一种适应不同功能类的版本。举个例子(如图):一台显示器与插座,我们可以通过一个多功能三相插头去统一显示器插头(两相、三相),还可以兼容不同功能的显示器。