重温设计模式

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

一、6大设计模式

1、单一职责原则

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

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

2、里斯替换原则

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

3、依赖倒置原则

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

4、接口隔离原则

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

5、迪米特原则

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

6、开闭原则

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

设计原则概括

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

二、23种设计模式

------------------------------创建型模式------------------------------

1、单例模式

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

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

2、工厂方法模式

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

>>工厂方法示例代码<<

3、抽象工厂模式

  为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类,可以理解为工厂方法的升级版。

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

4、建造者模式

  建造者模式也叫作生成器模式,将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。比如一个User类的属性有name、age、address、email、job...等,如果想创建一个User对象,传入全部的属性有点太长了,这时可以使用建造者模式,传入一个参数就只设置对应属性的值。

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

5、原型模式

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

>>原型模式<<

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

6、适配器模式

  适配器模式定义:将一个类的接口变换为客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

适配器模式的注意事项

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

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

7、装饰模式

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

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

8、代理模式

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

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

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

9、组合模式

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

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

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

10、门面模式

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

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

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

11、享元模式

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

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

12、桥接模式

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

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

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

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

13、责任链模式

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

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

14、迭代器模式

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

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

15、中介者模式

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

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

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

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

16、模板方法

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

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

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

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

17、状态模式

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

● State——抽象状态角色

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

● ConcreteState——具体状态角色

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

● Context——环境角色

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

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

18、策略模式

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

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

19、备忘录模式

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

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

20、观察者模式

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

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

21、访问者模式

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

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

22、命令模式

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

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

23、解释器模式

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

参考:

  1、《设计模式之禅》

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

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

时间: 2024-11-02 23:25:03

重温设计模式的相关文章

重温设计模式(一)—代理模式

通过这次设计模式的交流,发现无论是技术上还是思想上需要提升的空间还有很多.收获比预期的要多的多.给我触动最深的就是以下几点: 1. 面向对象的精华:抽象.封装.继承.多态 2.设计模式六大原则的运用:单一职责.开闭原则.合成聚合.依赖倒装.里氏代换.迪米特 3.让自己思绪飞翔-大胆的去想象,只有去想了.做了,你才知道最后的结果 初次学习代理模式的博文:http://blog.csdn.net/gxq741718618/article/details/8781099 下面用另外一种愉快的心情了解一

重温设计模式(三)——职责链模式(chain of responsibility)

一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所以希望各位多多指教. 二. 什么是链 文章伊始,先让我们了解这个最基本的概念,什么是链. 我给链下了这样的定义: 1. 链是一系列节点的集合. 2. 链的各节点可灵活拆分再重组. 三. 何为职责链 职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条

重温设计模式系列:文章发布计划

一.起因 从<大型网站架构系列>到<架构师入门实践>,一直想把代码设计和架构的知识进行总结,但是苦于精力和能力有限,推动起来比较缓慢.也多次收到出版社的邀请,但迟迟没有动笔.偶尔也会纠结做视频还是写文章,考虑到业余写作和工作之间的平衡,还是先以文章为主吧.写出来和大家交流,算是自己的一个知识总结,如果能帮到别人会更好.经过考虑,先出一个<设计模式系列>之后可以再根据情况总结一下别的.目标定下来,早晚都要走到,早走比晚走好. --2019-09-14 于昌平 二.背景 设

重温设计模式(2)—— 代理模式

用途 增强/替换原有类的行为 AOP编程 日志增强 权限控制 事务管理等 分类 静态代理 实现同一个接口 传入被代理对象 动态代理 jdk->Proxy.InvocationHandler实现 面向接口,生成与被代理类继承相同接口的class文件 反射调用(效率降低) cglib->基于ASM,修改被代理类class,生成其子类 生成class文件较慢? 参考: 处理注解:http://www.cnblogs.com/aheizi/p/4861422.html ASM原理:https://ww

设计模式之序章-UML类图那点事儿

设计模式之序-UML类图那点事儿 序 打14年年底就像写那么一个系列,用于讲设计模式的,代码基于JAVA语言,最早接触设计模式是大一还是大二来着,那时候网上有人给推荐书,其中就有设计模式,当时给我推荐的书我还隐约记得,叫GoF的,书名是<Design Patterns: Elements of Reusable Object-Oriented Software>,也即<设计模式>,机械出版社的将其翻译为<设计模式-可复用面向对象软件的基础>.至于为什么叫做GoF,那时候

atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换

atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3. 调用代码 2 4. 责任链链的特性: 2 5. 模式结构 4 6. 职责链模式包含如下角色:Handler,ConcreteHandler: 具体处理者,HandlerChainUtil ,Client 4 7. 设置哈一个handler,,两个法:排序法,指定法 5 1. 指定法 5 2. 排

《大话设计模式》读后感

第一次读<大话设计模式>,是在刚接触C#的时候.疲累于大部头的官方教材中时,无意间翻开了这本生动有趣的书,甚是眼前一亮.由于当时C#基础薄弱,只是把它当小说来看,如饥似渴,饶有滋味,一口气看到凌晨四点,被不知觉间流逝的时间吓傻了. 而今重读,更多的是想重温设计模式的应用场景和感受小菜对编程的热忱.一边做笔记一边看书,初步弄懂UML类图,效率果然高很多.感动也颇多.师傅领进门,修行看个人呀. 对程序员来说,精彩的代码是如何想出来的,要比看到精彩的代码更加令人期待.正如做一个足球运动员(软件设计编

第二十七天 春之细雨润物于无形 —Spring的依赖注入

6月11日,晴."夏条绿已密,朱萼缀明鲜.炎炎日正午,灼灼火俱燃." IT人习惯把具体的事物加工成的形状一致的类,正是这样的一致,加上合适的规范,才能彰显对象筋道的牙感和bean清香的味道.Spring比谁都清楚OO的奥妙,让组件之间的依赖关系由容器在运行时期决定,称作依赖注入(Dependency Injection). 下面用一通俗的例子,一探依赖注入奥妙. 设计模式中的一个原则:针对接口编程,不要针对实现编程. 一.设计两个接口: (1)奶制品接口-MilkProductInte

毕业工作已一年,回顾并记录学习内容

转眼工作已经满一年了,回首一年的经历,更多的是随遇而安:工作经验的与技术水平的累积没有想象中那么多.今天大概列举下一年的收获与不足,记录之前以及后续的目标. java: 熟悉语法:正在重温设计模式:需要更多的理会运用设计原则及模式.后序继续学习设计模式,性能分析.多查API接口文档:阅读JDK源码. web:以前迷迷糊糊的做项目,照着别人的代码敲也完成了工作:最近系统学习了下JavaScript,XML,jQuery,AJAX,Servlet&&JSP:明白了之前照敲的代码含义,也发现了以