重温设计模式

  设计模式,及软件设计中的“套路”。每个模式描述了一个在咱们周围不断重复发生的问题,以及该问题解决方案的核心,这样,你就能一次又一次的使用该方案而没必要作重复的劳动。设计模式大约有20多种,它们令人们能够更加简单方便的复用成功的设计和体系结构,提升系统维护的有效性。与设计模式密切相关的是6大设计原则,那么就从这些设计原则开始设计模式重温之旅吧。(ps:内容有点小多)java

1、6大设计模式

一、单一职责原则

  • 核心思想:应该有且仅有一个缘由引发类的变动
  • 问题描述:假若有类Class1完成职责T1,T2,当职责T1或T2有变动须要修改时,有可能影响到该类的另一个职责正常工做。
  • 好处:类的复杂度下降、可读性提升、可维护性提升、扩展性提升、下降了变动引发的风险。
  • 需注意: 单一职责原则提出了一个编写程序的标准,用“职责”或“变化缘由”来衡量接口或类设计得是否优良,可是“职责”和“变化缘由”都是不能够度量的,因项目和环境而异。

  单一职责就是让类(或方法)的功能单一,作到术业有且专攻,是否是有点UNIX设计思想的感受?git

 二、里斯替换原则

  • 核心思想:在使用基类的的地方能够任意使用其子类,能保证子类完美替换基类。
  • 通俗来说:只要父类能出现的地方子类就能出现。反之,父类则未必能胜任。
  • 好处:加强程序的健壮性,即便增长了子类,原有的子类还能够继续运行。
  • 需注意:若是子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系 采用依赖、聚合、组合等关系代替继承。

三、依赖倒置原则

  • 核心思想:高层模块不该该依赖底层模块,两者都该依赖其抽象;抽象不该该依赖细节;细节应该依赖抽象;
  • 说明:高层模块就是调用端,低层模块就是具体实现类。抽象就是指接口或抽象类。细节就是实现类。
  • 通俗来说:依赖倒置原则的本质就是经过抽象(接口或抽象类)使个各种或模块的实现彼此独立,互不影响,实现模块间的松耦合。
  • 问题描述:类A直接依赖类B,假如要将类A改成依赖类C,则必须经过修改类A的代码来达成。这种场景下,类A通常是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操做;假如修改类A,会给程序带来没必要要的风险。
  • 解决方案:将类A修改成依赖接口interface,类B和类C各自实现接口interface,类A经过接口interface间接与类B或者类C发生联系,则会大大下降修改类A的概率。
  • 好处:依赖倒置的好处在小型项目中很难体现出来。但在大中型项目中能够减小需求变化引发的工做量。使并行开发更友好。

四、接口隔离原则

  • 核心思想:类间的依赖关系应该创建在最小的接口上
  • 通俗来说:创建单一接口,不要创建庞大臃肿的接口,尽可能细化接口,接口中的方法尽可能少。也就是说,咱们要为各个类创建专用的接口,而不要试图去创建一个很庞大的接口供全部依赖它的类去调用。
  • 问题描述:类A经过接口interface依赖类B,类C经过接口interface依赖类D,若是接口interface对于类A和类B来讲不是最小接口,则类B和类D必须去实现他们不须要的方法。
  • 需注意:
    • 接口尽可能小,可是要有限度。对接口进行细化能够提升程序设计灵活性,可是若是太小,则会形成接口数量过多,使设计复杂化。因此必定要适度
    • 提升内聚,减小对外交互。使接口用最少的方法去完成最多的事情
    • 为依赖接口的类定制服务。只暴露给调用的类它须要的方法,它不须要的方法则隐藏起来。只有专一地为一个模块提供定制服务,才能创建最小的依赖关系。

五、迪米特原则

  • 核心思想:类间解耦。
  • 通俗来说: 一个类对本身依赖的类知道的越少越好。自从咱们接触编程开始,就知道了软件编程的总的原则:低耦合,高内聚。不管是面向过程编程仍是面向对象编程,只有使各个模块之间的耦合尽可能的低,才能提升代码的复用率。低耦合的优势不言而喻,可是怎么样编程才能作到低耦合呢?那正是迪米特法则要去完成的。

六、开闭原则

  • 核心思想:尽可能经过扩展软件实体来解决需求变化,而不是经过修改已有的代码来完成变化
  • 通俗来说: 一个软件产品在生命周期内,都会发生变化,既然变化是一个既定的事实,咱们就应该在设计的时候尽可能适应这些变化,以提升项目的稳定性和灵活性。

设计原则归纳

  单一职责原则告诉咱们实现类要职责单一;里氏替换原则告诉咱们不要破坏继承体系;依赖倒置原则告诉咱们要面向接口编程;接口隔离原则告诉咱们在设计接口的时候要精简单一;迪米特法则告诉咱们要下降耦合。而开闭原则是总纲,他告诉咱们要对扩展开放,对修改关闭。github

 

2、23种设计模式

------------------------------建立型模式------------------------------

一、单例模式

  单例模式确保一个类只有一个实例,自行初始化并向整个系统提供这个实例。一个类只有一个实例减小了内存开支,特别是一个对象频繁建立销毁时。单例模式可细分为2种模式,饿汉式和懒汉式,两者的区别是初始化实例的时间不一样,前者是在定义时就初始化,后者是在第一次使用时初始化,这里注意多线程的并发访问。算法

>>单例模式示例代码<<编程

二、工厂方法模式

  工厂方法(Factory Method)模式的意义是定义一个建立产品对象的工厂接口,将实际建立工做推迟到子类当中。核心工厂类再也不负责产品的建立,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可使系统在不修改具体工厂角色的状况下引进新的产品。设计模式

>>工厂方法示例代码<<数据结构

三、抽象工厂模式

  为建立一组相关或相互依赖的对象提供一个接口,并且无须指定它们的具体类,能够理解为工厂方法的升级版。多线程

>>抽象工厂示例代码<<并发

四、建造者模式

  建造者模式也叫做生成器模式,将一个复杂对象的构建和它的表示分离,使得一样的构建过程能够建立不一样的表示。好比一个User类的属性有name、age、address、email、job...等,若是想建立一个User对象,传入所有的属性有点太长了,这时可使用建造者模式,传入一个参数就只设置对应属性的值。框架

>>建造者模式示例代码<<

五、原型模式

  原型模式的定义为:用原型实例指定建立对象的种类,而且经过拷贝这些原型建立新的对象。原型模式的核心是一个clone()方法,经过该方法进行对象的复制,Java提供了一个Cloneable来标示这个对象是可拷贝的,为何说是“标示”呢?这个接口只是一个标记做用,在JVM中具备这个标记的对象才有可能被拷贝。那怎么才能从“有可能被拷贝”到“能够被拷贝”呢?方式就是覆盖clone()方法

>>原型模式<<

 

------------------------------结构型模式------------------------------

六、适配器模式

  适配器模式定义:将一个类的接口变换为客户端所期待的另外一种接口,从而使本来因接口不匹配而没法在一块儿工做的两个类可以在一块儿工做。

适配器模式的注意事项

  适配器模式最好在详细设计阶段不要考虑它, 它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,没有一个系统分析师会在作详细设计的时候考虑使用适配器模式,这个模式使用的主要场景是扩展应用中,就像咱们上面的那个例子同样,系统扩展了,不符合原有设计的时候才考虑经过适配器模式减小代码修改带来的风险。

>>适配器模式示例代码<<

七、装饰模式

  动态地给一个对象添加额外的职责,就增长功能来讲,装饰模式相比于生成子类更加灵活。装饰模式至关于在一个构建类外层添加了一个包裹类。

>>装饰模式示例代码<<

八、代理模式

  代理模式是一种使用率很是高的模式,为其余对象提供一种代理以控制对这个对象的访问。

  在Java中有一种动态代理技术,动态代理指实现阶段不用关心代理谁,而在运行阶段才指定代理哪个对象。

>>代理模式示例代码<<

九、组合模式

  组合模式将对象组合成树形结构以表示“总体-部分”的层次结构,使得用户对单个对象和组合对象的使用具备一致性。

  • Component抽象构件角色:定义参加组合对象的共有方法和属性, 能够定义一些默认的行为或属性, 好比咱们例子中的getInfo就封装到了抽象类中。
  • Leaf叶子构件:叶子对象, 其下再也没有其余的分支, 也就是遍历的最小单位。
  • Composite树枝构件:树枝对象, 它的做用是组合树枝节点和叶子节点造成一个树形结构。

>>组合模式示例代码<<

十、门面模式

  门面模式要求一个子系统的外部与其内部的通讯必须经过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。

  • Facade门面角色:客户端能够调用这个角色的方法。 此角色知晓子系统的全部功能和责任。 通常状况下,本角色会将全部从客户端发来的请求委派到相应的子系统去, 也就说该角色没有实际的业务逻辑, 只是一个委托类。
  • subsystem子系统角色:能够同时有一个或者多个子系统。 每个子系统都不是一个单独的类, 而是一个类的集合。 子系统并不知道门面的存在。 对于子系统而言, 门面仅仅是另一个客户端而已。

>>门面模式示例代码<<

十一、享元模式

  享元模式是池技术的重要实现,使用共享对象可有效地支持大量的细粒度的对象。

>>享元模式示例代码<<

十二、桥接模式

  桥梁模式定义:将抽象和实现解耦,使得二者能够独立的变化。

  • Abstraction——抽象化角色:它的主要职责是定义出该角色的行为, 同时保存一个对实现化角色的引用, 该角色通常是抽象类。
  • Implementor——实现化角色:它是接口或者抽象类, 定义角色必需的行为和属性。
  • RefinedAbstraction——修正抽象化角色:它引用实现化角色对抽象化角色进行修正。
  • ConcreteImplementor——具体实现化角色:它实现接口或抽象类定义的方法和属性。

>>桥接模式示例代码<<

 

------------------------------行为模式------------------------------

1三、责任链模式

  责任链模式定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象组成一条链,并沿着这条链来传递请求,直到有对象处理它为止。

>>责任链模式示例代码<<

1四、迭代器模式

  迭代器模式提供了一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节(目前已不多用到了,容器通常都提供了迭代器)。

>>迭代器模式示例代码<<

1五、中介者模式

  用一个中介对象封装一系列的对象交互,中介者使各对象不须要显示地互相做用,从而使其耦合松散,并且能够独立地改变它们之间的交互。

终结者模式的优势:减小类间的依赖,把原来的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,较少了依赖,下降了类间的耦合。

终结者模式的缺点:终结者会膨胀的很大,并且逻辑很复杂,原来N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑越复杂。

>>中介者模式设计模式<<

1六、模板方法

  定义一个操做中算法的框架,而将一些步骤延迟到子类中。使得子类能够不改变一个算法便可重定义该算法的某些特定步骤。

基本方法:也叫做基本操做,是由子类实现的方法,而且在模板方法被调用

模板方法:能够有一个或几个, 通常是一个具体方法, 也就是一个框架, 实现对基本方法的调度,完成固定的逻辑。通常将模板方法加上final关键字,不容许被覆写

>>模板方法示例代码<<

1七、状态模式

  状态模式定义:当一个对象内在状态改变时容许其改变行为,这个对象看起来像改变了其类。状态模式的核心是封装,状态的变动引发了行为的变动,从外部看起来就好像这个对象对应的类发生了改变同样。 

● State——抽象状态角色

  接口或抽象类, 负责对象状态定义, 而且封装环境角色以实现状态切换。

● ConcreteState——具体状态角色

  每个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要作的事情, 以及本状态如何过渡到其余状态。

● Context——环境角色

  定义客户端须要的接口, 而且负责具体状态的切换。

>>状态模式示例代码<<

1八、策略模式

  策略模式是比较简单的模式,定义一组算法,将每一个算法封装起来,而且使它们之间能够互换。

>>策略模式示例代码<<

1九、备忘录模式

  备忘录模式定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象以外保存这个状态。这样之后就可将该对象恢复到原先保存的状态。

>>备忘录模式示例代码<<

20、观察者模式

  观察者模式(Observer Pattern)也叫做发布订阅模式,其定义以下:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则全部依赖于它的对象都会获得通知并自动更新。

>>观察者模式示例代码<<

2一、访问者模式

  封装一些做用于某种数据结构中的个元素的操做,它能够在不改变数据结构的前提下定义做用于这些元素的新的操做。

>>访问者模式示例代码<<

2二、命令模式

  命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用功能不一样的请求把客户端参数化,对请求排列或记录请求日志,能够提供命令的撤销和恢复功能。

>>命令模式示例代码<<

2三、解释器模式

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

 

参考:

  一、《设计模式之禅》

  二、《设计模式-可复用面对对象软件的基础》

  三、https://github.com/luoxn28/ThinkInTechnology/tree/master/DesignPattern

相关文章
相关标签/搜索