1.简单的工厂模式
有感:工厂类包含必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
2.策略模式
定义:它定义了算法家族,分别分装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
有感:策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为,继承有助于折取出这些算法中的公共功能,同时简化了单元测试,因为每个算法都有自己的类,可以通过自己的借口单独测试。
使用场景:策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性
3.单一职责原则(SRP)
定义:就一个类而言,应该仅有一个引起它变化的原因。
有感:如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受意想不到的破坏。软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。如果你能偶想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。
4.开放-封闭原则
定义:是说软件实体(类,模块,函数等待)应该可以扩展,但是不可修改。
有感:无论模块是多么的‘封闭’,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭作出选择。他必须先猜测出最有可能发生变化种类,然后构造构造抽象来隔离那些变化。在我们最初编写代码时,假设变化不会发生。当变化发生时,我们就创建抽象来隔离以后发生变化的同类变化。面对需求,对程序的改动时通过增加新代码进行的,而不是更改现有的代码。我们希望的是在开发工作展开不久就知道可能发生的变化。查明可能发生的变化所等待的时间越长,要创建的抽象久越困难。
优点:开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护,可拓展,可服用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。
5.依赖倒转原则
定义:高层模块不应该依赖底层模块。两个都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
里氏代换原则(LSP)
定义:子类型必须能够替换掉它们的父类型。
有感:针对接口编程,不要对实现编程只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而之类也能够在父类的基础上增加新的行为。由于有里氏代换原则,才使得开放-封闭成为了可能。正是由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展。依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类活着接口,那就是面向对象的设计,反之那就是过程化的设计了。
6. 装饰模式
定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
有感:Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decoratotrde的存在的。至于ConcreDecorator就是具体的装饰对象,起到给Component添加职责的功能。装饰模式是利用set Component来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。
使用场景:装饰模式是为已有功能动态地添加更多功能的一种方式。当系统需要新功能的时候 ,是向旧的类添加新的代码,这些新的代码通常装饰了原有类的核心职责或主要行动,在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足一些旨在特定情况下才会执行的特殊行为的需要,装饰模式却提供了一个好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行根据需要有徐泽地、按顺序地使用装饰功能包装对象了。
优点:把类中的功能从类中搬移去除,这样可以简化原有的类。有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
7.代理模式
定义:为其他对象提供一种代理以控制这个对象的访问。
使用场景:远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实;虚拟代理,是根据需要创建要开销很大的对象。通过它来存在实例化需要很长时间的真实对象;安全代理,用来控制真实对象访问时的权限;智能指引,是指当调用真实的对象时,代理处理另外一些事。
8.工厂方法模式
定义:定义一个用于创建对象的接口,让子类决定实例化哪一类。工厂方法使一个类的实例化延迟到其子类。
有感:和简单工厂模式的区别是客户的需要决定实例化哪一个工厂来实现运算类选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你想要加功能,本来是改工厂类的,而现在是修改客户端。
9.原型模式
定义:用原型实例指定创建的对象的种类,并且通过拷贝这些原型创建新的对象
有感:原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。
10.模版方法模式
定义:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。
有感:模版方法模式是通过把不变行为搬移到超类,去除子类中重复代码来体现它的优势,提供了一个很好的代码复用平台,当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现,通过模版方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。
11.迪米特法则
定义:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
有感:在类的结构设计上,每一个类都应当尽量降低成员的访问权限,根本思想是强调了类之间的送耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。
12.外观模式
定义:为子系统中的一组提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
使用场景:首先,在设计初期阶段,应该要有意识的将不同的两个层分离,比如在经典的三层架构中,就需要考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观Facade,为辅助的子系统提供一个煎蛋的接口,其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观Facade可以提供一个煎蛋的接口,减少它们之间的依赖。第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,为新系统开发一个外观Facade类,类提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。
13.建造者模式
定义:将一个复杂对象的构建与它的表示分离,使得同意的构建过程创建不同的表示。
有感:Builder是为创建一个Product对象的各个部件制定的抽象接口,ConcreteBuilder是具体建造者,实现Builder接口,构造和装配各个部件。Product当然就是那些具体的产品角色。Director是构建一个使用Builder接口的对象,它主要是用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。建造者模式的好处就是使得建造代码和表示代码分离,由于建造者隐藏了改产品是如何组装的,所以若需要改变一个产品内部表示,只需要再定义一个具体的建造就可以了。建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。
14.观察者模式
定义:该模式定义了一种一对多的依赖关系,让多个观察者对像同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
有感:将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性,我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、拓展和重用都带来不便。而观察者模式的关键对象时主题Subject和观察者Observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生了改变,所有的Observer都可以得到通知。Subject发出通知时并不需要知道谁时它的观察者,也就是说,具体观察者时谁,它根本不需要知道。而任何一个具体观察者不知道也不需要知道其他观察者的存在。
使用场景:当一个对象的改变需要同时改变其他对象的时候,而去它不知道具体有多少对象有待改变时,应该考虑使用观察者模式。当一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。总的来讲,观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
15.抽象工厂模式
定义:提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
有感:AbstractProductA和AbstractProductB时两个抽象产品,因为它们都有可能有两个种不同的实现,ProductA1、ProductA2、ProductB1、ProductB2就是对两个抽象产品的具体分类实现,AbstractFactory是一个抽象工厂接口,它里面应该包含所有产品创建的抽象方法,而ConcreteFactory1和ConcreteFactory2就是具体工厂了。通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建有特定实现的产品对象,也就是说,为创建不同产品对象,客户端应使用不同的具体工厂。
优点:最大的好处是易于交换产品系列,由于具体工厂类,在一个应用中只需要初始化的时候出现一次,这就使得改变一个应用的具体工厂变的非常容易,它只需要改变具体工厂即可使用不同的产品配置。第二个好处是它让具体的创建实例过程于客户端分离,客户端通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
缺点:如果需要增加一个product,就需要增加product的抽象类和具体的子类,同时需要修改工厂类的代码,这样违反了开放封闭原则,客户端还会出现具体工厂的代码,可以通过反射+简单工厂+配置文件的方式来改进。
16.状态模式
定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
有感:状态模式主要解决的是控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
优点:它将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。也就是将特定的状态相关行为都放入一个对象中,由于所有与状态相关的代码都窜在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换,目的就是消除庞大的条件分支语句。通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
使用场景:当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
17.适配器模式
定义:将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原来由于接口不兼容而不能一起工作的那些类可以一起工作
有感:当系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。