#0 系列目录#算法
#1 建立型模式#编程
简单工厂模式(Simple factory pattern): 提供一个建立对象实例的功能,而无需关心具体的实现
。被建立实例的类能够是接口、抽象类,也能够是具体的类。设计模式
工厂方法模式(Factory method pattern): 定义了一个建立对象的接口, 但由子类决定要实例化的类是哪个
。工厂方法让类把实例化推迟到子类。框架
抽象工厂模式(Abstract factory pattern): 提供一个接口, 用于建立相关或依赖对象的家族, 而不须要指定具体类
。函数
生成器模式(Builder pattern): 使用生成器模式封装一个产品的构造过程, 并容许按步骤构造
。将一个复杂对象的构建与它的表示分离, 使得一样的构建过程能够建立不一样的表示。性能
原型模式(Prototype pattern): 当建立给定类的实例过程很昂贵或很复杂时
, 就使用原形模式。学习
单例模式(Singleton pattern): 确保一个类只有一个实例
, 并提供全局访问点。ui
#2 结构型模式#.net
适配器模式(Adapter pattern): 将一个类的接口, 转换成客户指望的另外一个接口
。适配器让本来接口不兼容的类能够合做无间。对象适配器使用组合, 类适配器使用多重继承。设计
桥接模式(Bridge pattern): 使用桥接模式经过将实现和抽象放在两个不一样的类层次中而使它们能够独立改变
。
组合模式(Composite pattern): 容许你将对象组合成树形结构来表现"总体/部分"层次结构。组合能让客户以一致的方式处理个别对象以及对象组合
。
装饰者模式(Decorator pattern): 动态地将责任附加到对象上
, 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案。
外观模式(Facade pattern): 提供了一个统一的接口, 用来访问子系统中的一群接口
。外观定义了一个高层接口, 让子系统更容易使用。
亨元模式(Flyweight Pattern): 如想让某个类的一个实例能用来提供许多"虚拟实例"
, 就使用蝇量模式。
代理模式(Proxy pattern): 为另外一个对象提供一个替身或占位符以控制对这个对象的访问
。
#3 行为型模式#
责任链模式(Chain of responsibility pattern): 经过责任链模式, 你能够为某个请求建立一个对象链
。每一个对象依序检查此请求并对其进行处理或者将它传给链中的下一个对象。
命令模式(Command pattern): 将"请求"封闭成对象, 以便使用不一样的请求,队列或者日志来参数化其余对象
. 命令模式也支持可撤销的操做。
解释器模式(Interpreter pattern): 使用解释器模式为语言建立解释器
。
迭代器模式(Iterator pattern): 提供一种方法顺序访问一个聚合对象中的各个元素
, 而又不暴露其内部的表示。
中介者模式(Mediator pattern) : 使用中介者模式来集中相关对象之间复杂的沟通和控制
方式。
备忘录模式(Memento pattern): 当你须要让对象返回以前的状态时(例如, 你的用户请求"撤销")
, 你使用备忘录模式。
观察者模式(Observer pattern): 在对象之间定义一对多的依赖, 这样一来, 当一个对象改变状态, 依赖它的对象都会收到通知, 并自动更新
。
状态模式(State pattern): 容许对象在内部状态改变时改变它的行为
, 对象看起来好象改了它的类。
策略模式(Strategy pattern): 定义了算法族, 分别封闭起来, 让它们之间能够互相替换
, 此模式让算法的变化独立于使用算法的客户。
模板方法模式(Template pattern): 在一个方法中定义一个算法的骨架, 而将一些步骤延迟到子类中
. 模板方法使得子类能够在不改变算法结构的状况下, 从新定义算法中的某些步骤。
访问者模式(Visitor pattern): 当你想要为一个对象的组合增长新的能力, 且封装并不重要时, 就使用访问者模式
。
#4 设计模式和设计原则# ##4.1 设计模式和设计原则的关系## 面向对象的分析设计有不少原则,这些原则大都从思想层面,给咱们指出了面向对象分析设计的正确方向,是咱们进行面向对象分析设计应该尽力遵照的准则。
而设计模式已是针对某个场景下某些问题的某个解决方案。也就是说这些设计原则是思想上的指导,而设计模式是实现上的手段,所以设计模式也是应该遵照这些原则的,换句话说,设计模式就是这些设计原则的一些具体体现
。
##4.2 为什么不重点讲设计原则## 既然设计模式是这些设计原则的具体体现,那也就意味着设计模式的思想上的根就是这些设计原则了,没错,能够这么认为。这样一来,有些朋友就会很疑惑了,那么为什么不重点讲讲设计原则呢?
对于这个问题,咱们有以下的考虑:
设计原则自己是从思想层面上进行指导,自己是高度归纳和原则性的,只是一个设计上的大致方向,其具体实现并非只有设计模式这一种
。理论上来讲,能够在相同的原则指导下,作出不少不一样的实现来。
每一种设计模式并非单一的体现某一个设计原则,事实上,不少设计模式都是融合了不少个设计原则的思想,并很差特别强调设计模式对某个或者是某些设计原则的体现
。并且每一个设计模式在应用的时候也会有不少的考量,不一样使用场景下,突出体现的设计原则也多是不同的。
这些设计原则只是一个建议指导,事实上,在实际开发中,不多作到彻底遵照,老是在有意无心的违反一些或者是部分设计原则
。设计工做原本就是一个不断权衡的工做,有句话说得很好:“设计是一种危险的平衡艺术”
,设计原则只是一个指导,有些时候,还要综合考虑业务功能、实现的难度、系统性能、时间与空间等不少方面的问题。设计模式自己已经很复杂了,已经很难再去深刻的探讨这些设计原则,这样也避免出现过多的重点内容,致使你们无所适从。
#5 常见的面向对象设计原则# ##5.1 单一职责原则SRP(Single Responsibility Principle)## 所谓单一职责原则,指的就是:一个类应该仅有一个引发它变化的缘由。
这里变化的缘由就是所说的“职责”,若是一个类有多个引发它变化的缘由,那么也就意味着这个类有多个职责,再进一步说,就是把多个职责耦合在一块儿了。
这会形成职责的相互影响,可能一个职责的变化,会影响到其它职责的实现,甚至引发其它职责跟着变化,这种设计是很脆弱的。
这个原则看起来是最简单和最好理解的,可是其实是很难彻底作到的,难点在于如何区分这个“职责”
,这是个没有标准量化的东西,哪些算职责,到底这个职责有多大的粒度,这个职责如何细化等等。所以,在实际开发中,这个原则也是最容易违反的。
##5.2 开放-关闭原则OCP(Open-Closed Principle)## 所谓开放-关闭原则,指的就是:一个类应该对扩展开放,对修改关闭。通常也被简称为开闭原则,开闭原则是设计中很是核心的一个原则。
开闭原则要求的是,类的行为是能够扩展的
,并且是在不修改已有的代码的状况下进行扩展,也没必要改动已有的源代码或者二进制代码。
看起来好像是矛盾的,怎么样才能实现呢?
实现开闭原则的关键就在于合理的抽象,分离出变化与不变化的部分,为变化的部分预留下可扩展的方式
,好比:钩子方法、或是动态组合对象等等。
这个原则看起来也很简单,但事实上,一个系统要所有作到遵照开闭原则,几乎是不可能的
,也没这个必要。适度的抽象能够提升系统的灵活性,使其可扩展、可维护,可是过分的抽象,会大大增长系统的复杂程度
。应该在须要改变的地方应用开闭原则就能够了,而不用处处使用,从而陷入过分设计。
##5.3 里氏替换原则LSP(Liskov Substitution Principle)## 所谓里氏替换原则,指的就是:子类型必须可以替换掉它们的父类型。
这很明显是一种多态的使用状况,它能够避免在多态的应用中,出现某些隐蔽的错误。
事实上,当一个类继承了另一个类,那么子类就拥有了父类中能够继承下来的属性和操做,理论上来讲,此时使用子类型去替换掉父类型,应该不会引发原来使用父类型的程序出现错误。
可是,很不幸的是,在某些状况下是会出现问题的,好比:若是子类型覆盖了父类型的某些方法,或者是子类型修改了父类型某些属性的值,那么原来使用父类型的程序就可能会出现错误
,由于在运行期间,从表面上看,它调用的是父类型的方法,须要的是父类型方法实现的功能,可是实际运行调用的确是子类型覆盖实现的方法,而该方法跟父类型的方法并不同,那就会致使错误的产生
。
从另一个角度来讲,里氏替换原则是实现开闭的主要原则之一,开闭原则要求对扩展开放,扩展的一个实现手段就是使用继承,而里氏替换原则是保证子类型可以正确替换父类型,只有能正确替换,才能实现扩展,不然扩展了也会出现错误
。
##5.4 依赖倒置原则DIP(Dependence Inversion Principle)## 所谓依赖倒置原则,指的就是:要依赖于抽象,不要依赖于具体类。
要作到依赖倒置,典型的应该作到:
高层模块不该该依赖于底层模块,两者都应该依赖于抽象;
抽象不该该依赖于具体实现,具体实现应该依赖于抽象;
不少人以为,层次化调用的时候,应该是高层调用“底层所拥有的接口”,这是一种典型的误解
。事实上,通常高层模块包含对业务功能的处理和业务策略选择,应该被重用,应该是高层模块去影响底层的具体实现
。
所以,这个底层的接口,应该是由高层提出的,而后由底层实现的,也就是说底层的接口的全部权在高层模块,所以是一种全部权的倒置
。
倒置接口全部权,这就是著名的Hollywood(好莱坞)原则:不要找咱们,咱们会联系你
。
##5.5 接口隔离原则ISP(Interface Segregation Principle)## 所谓接口隔离原则,指的就是:不该该强迫客户依赖于他们不用的方法。
这个原则用来处理那些比较“庞大”的接口,这种接口一般会有较多的操做声明,涉及到不少的职责。客户在使用这样的接口的时候,一般会有不少它不须要的方法,这些方法对于客户来说,就是一种接口污染,至关于强迫用户在一大堆“垃圾方法”里面去寻找他须要的方法
。
所以,这样的接口应该被分离,应该按照不一样的客户须要来分离成为针对客户的接口
,这样的接口里面,只包含客户须要的操做声明,这样既方便了客户的使用,也能够避免因误用接口而致使的错误。
分离接口的方式,除了直接进行代码分离以外,还可使用委托来分离接口
,在可以支持多重继承的语言里面,还能够采用多重继承的方式进行分离。
##5.6 最少知识原则(Least Knowledge Principle)## 所谓最少知识原则,指的就是:只和你的朋友谈话。
这个原则用来指导咱们在设计系统的时候,应该尽可能减小对象之间的交互,对象只和本身的朋友谈话,也就是只和本身的朋友交互,从而松散类之间的耦合
。经过松散类之间的耦合来下降类之间的相互依赖,这样在修改系统的某一个部分时候,就不会影响其它的部分,从而使得系统具备更好的可维护性。
那么究竟哪些对象才能被看成朋友呢?最少知识原则提供了一些指导:
当前对象自己;
经过方法的参数传递进来的对象;
当前对象所建立的对象;
当前对象的实例变量所引用的对象;
方法内所建立或实例化的对象;
总之,最少知识原则要求咱们的方法调用,必须保持在必定的界限范围以内,尽可能减小对象的依赖关系
。
##5.7 其它原则## 除了上面提到的这些原则,还有一些你们都熟知的原则,好比:
面向接口编程;
优先使用组合/聚合,而非继承;
固然也还有不少你们不是很熟悉的原则,好比:
一个类须要的数据应该隐藏在类的内部;
类之间应该零耦合,或者只有传导耦合,换句话说,类之间要么没有关系,要么只使用另外一个类的接口提供的操做;
在水平方向上尽量统一的分布系统功能;
#6 设计原则总结#
单一职责原则【SINGLE RESPONSIBILITY PRINCIPLE】:一个类负责一项职责。
里氏替换原则【LISKOV SUBSTITUTION PRINCIPLE】:继承与派生的规则。
依赖倒置原则【DEPENDENCE INVERSION PRINCIPLE】:高层模块不该该依赖低层模块,两者都应该依赖其抽象;抽象不该该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程。
接口隔离原则【INTERFACE SEGREGATION PRINCIPLE】:创建单一接口,不要创建庞大臃肿的接口,尽可能细化接口,接口中的方法尽可能少。
迪米特法则【LOW OF DEMETER】:低耦合,高内聚。
开闭原则【OPEN CLOSE PRINCIPLE】:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
组合/聚合复用原则【Composition/Aggregation Reuse Principle(CARP)】:尽可能使用组合和聚合少使用继承的关系来达到复用的原则。
#7 不是结束而是新的开始# 到此,设计模式系列已经讲完结束了,但偏偏相反,要想在设计上更进一步的话,困难才刚刚开始。更多的是须要思考和领悟,其难度比从入门到中级要大得多。
所以对你而言,看完本系列并非学习的结束,而是新的开始。
##7.1 你该怎么作## 若是已经深刻领会和掌握了本书的内容,还想要在设计模式上继续精进的朋友,给出以下的建议:
多搜寻一些应用设计模式的实际项目、工程或是框架,参考别人的成功应用,再结合本身的经验来思考和使用。固然项目不该该太大,太大了很难彻底看懂;也不能过小,过小了,没有太大实用价值,尤为是没法参考多个模式综合应用的状况,帮助就不大了。
多寻找机会,把这些设计模式在实际应用中使用,只有亲自动手去试验和使用,才能真正掌握和领会设计模式的精髓。
认真分析每次对设计模式的使用是否得当,有什么经验和教训,是否有变形使用的状况,在不断总结中进步。
理论联系实际,经过实际应用反过来加深对理论的理解,以达到融会贯通这些设计模式的知识。所以,你须要反复参阅本系列,而后实践,而后再回头看系列上的知识,你会有不同的体会和领悟。
多从设计上去思考这些设计模式,考虑它的设计意图、设计思想、解决问题的方式、实现的原理、模式的本质、以及如何变形使用等等。