赞
踩
学习编程开发,设计模式几乎是必学的,但是设计模式比较多,非常容易弄混,也不容易理解。所以将设计模式的精要总结下来,方便理解。
设计模式是一套面向对象的代码设计经验总结,是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。是一种思想,而非具体的技术。
1995 年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。
设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。正确使用设计模式具有以下优点:
以下为简单总结七大设计原则的概念和特点,如果想要详细了解七大设计原则,请参考我的博客:
一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。
客户端不应该被迫依赖于它不使用的方法,一个类对另一个类的依赖应该建立在最小的接口上。
理解:要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
接口隔离原则是为了约束接口、降低类对接口的依赖性,遵循接口隔离原则有以下 优点:
接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两者是不同的:
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
核心思想:要面向接口编程,不要面向实现编程。
依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
继承必须确保超类所拥有的性质在子类中仍然成立。
理解:
软件实体应当对扩展开放,对修改关闭。
这里的软件实体包括以下几个部分:
含义:
当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。
开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。具体来说,其作用如下。
软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。
如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。
目的:降低类之间的耦合度,提高模块的相对独立性。
迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。
迪米特法则要求限制软件实体之间通信的宽度和深度,正确使用迪米特法则将有以下两个优点。
但是,过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低。所以,在釆用迪米特法则时需要反复权衡,确保高内聚和低耦合的同时,保证系统的结构清晰。
尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
**如果要使用继承关系,则必须严格遵循里氏替换原则。**合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
通常类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优点,但它也存在以下缺点。
采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点。
在软件系统中,类不是孤立存在的,类与类之间存在各种关系。根据类与类之间的耦合度从弱到强排列,UML 中的类图有以下几种关系:依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现关系。其中泛化和实现的耦合度相等,它们是最强的。
以下为简单总结类之间的关系,如果想要详细了解,请参考我的博客:
依赖(Dependency)关系是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。在代码中,某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类(被依赖类)中的某些方法来完成一些职责。
只要是在类中用到了对方,那么他们之间就存在依赖关系。
关联(Association)关系是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系,如老师和学生、师傅和徒弟、丈夫和妻子等。
聚合(Aggregation)关系是关联关系的一种,是强关联关系,是整体和部分之间的关系,是 has-a 的关系。
聚合关系也是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在。例如,学校与老师的关系,学校包含老师,但如果学校停办了,老师依然存在。
组合(Composition)关系也是关联关系的一种,也表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系,是 cxmtains-a 关系。
在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系,没有了头,嘴也就不存在了。
泛化(Generalization)关系是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系,是 is-a 的关系。
实现(Realization)关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,不需要知道商品是怎么生产出来一样,因为它们由专门的厂商生产。
某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例。
单例模式有 3 个特点:
优点
在系统设置全局的访问点,优化环共享资源访问
只生成一个实例,减少了系统性能开销
单例模式详情参考我的博客:设计模式(三)——详解单例模式(Singleton Pattern)的8种写法
实现了创建者和调用者的分离。将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
工厂模式详情参考我的博客:设计模式(四)——工厂模式(Factory Pattern)
如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”。
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
工厂方法模式的主要优点有:
其缺点是:增加了系统的复杂度(每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类)。
提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
使用抽象工厂模式一般要满足以下条件。
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
优点
允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。
原型模式详情参考我的博客:设计模式(五)——原型模式(Prototype Pattern)
将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象(构建和装配的解耦)。
本质
分离了对象子组件的单独构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况下使用。
由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。
建造者模式详情参考我的博客:设计模式(六)——建造者模式(Builder Pattern)
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。
由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
分类
优点
缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。
适配器模式详情参考我的博客:设计模式(七)——适配器模式(Adapter Pattern)
将抽象与实现放在两个不同的类层次中,使两个层次可以独立改变。
主要特点
核心要点
处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联。
桥接模式详情参考我的博客:设计模式(八)——桥接模式(Bridge Pattern)
动态地给对象增加一些职责,即增加其额外的功能。
装饰模式是一种用于代替继承的技术 ,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
装饰(Decorator)模式的主要优点有:
其主要缺点是:装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。
装饰者模式详情参考我的博客:设计模式(九)——装饰者模式(Decorator Pattern)
又叫部分整体模式,将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性,可以使用统一的方式处理部分对象和整体对象。
组合模式的主要优点有:
其主要缺点是:
组合模式详情参考我的博客:设计模式(十)——组合模式(Composite Pattern)
为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
外观(Facade)模式是“迪米特法则”的典型应用,它有以下主要优点。
外观(Facade)模式的主要缺点如下。
外观模式详情参考我的博客:设计模式(十一)——外观模式(Facade Pattern)
运用共享技术来有效地支持大量细粒度对象的复用。
关键
享元对象能做到共享的关键是区分了内部状态和外部状态。
它通过共享已经存在的又橡来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
享元模式的主要优点是:相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
其主要缺点是:
外观模式详情参考我的博客:设计模式(十二)——享元模式(Flyweight Pattern)
为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
代理模式的主要优点有:
其主要缺点是:
代理模式详情参考我的博客:设计模式(十三)——代理模式(Proxy Pattern)
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。
定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
该模式的主要优点如下。
该模式的主要缺点如下。
模板方法模式详情参考我的博客:设计模式(十四)——模板方法模式(Template Method Pattern)
将一个请求封装为一个对象,使得请求发送者与请求接收者实现解耦。
命令模式的主要优点如下。
其缺点是:可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。
命令模式详情参考我的博客:设计模式(十五)——命令模式(Command Pattern)
将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。
它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
访问者(Visitor)模式是一种对象行为型模式,其主要优点如下。
访问者(Visitor)模式的主要缺点如下。
访问者模式详情参考我的博客:设计模式(十六)——访问者模式(Visitor Pattern)
提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构。
什么时候使用?
如果我们的集合元素是用不同的方式实现的,有数组,还有 java 的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。
主要优点如下。
其主要缺点是:增加了类的个数,这在一定程度上增加了系统的复杂性。
迭代器模式详情参考我的博客:设计模式(十七)——迭代器模式(Iterator Pattern)
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式。
核心
观察者模式主要用于1 : N的通知。当一个对象(目标对象Subject或Objservable)的状态变化时(消息发布);他需要及时告知一系列对象(观察者对象,Observer) ,令他们做出响应(消息订阅)。
通知观察者的方式:
消息订阅
●推
●拉
观察者模式是一种对象行为型模式,其主要优点如下。
它的主要缺点如下。
目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
迭代器模式详情参考我的博客:设计模式(十八)——观察者模式(Observer Pattern)
定义一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,降低系统中对象间的耦合度,而且可以独立地改变它们之间的交互。
中介者模式是一种对象行为型模式,其主要优点如下。
其主要缺点是:当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。
迭代器模式详情参考我的博客:设计模式(十九)——中介者模式(Mediator Pattern)
在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
备忘录模式是一种对象行为型模式,其主要优点如下。
其主要缺点是:资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
备忘录模式详情参考我的博客:设计模式(二十)——备忘录模式(Memento Pattern)
提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。
注意:解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题。如果碰到对表达式的解释,在 Java 中可以用 Expression4J 或 Jep 等来设计。
解释器模式详情参考我的博客:设计模式(二十一)——解释器模式(Interpreter Pattern)
对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
状态模式是一种对象行为型模式,其主要优点如下。
状态模式的主要缺点如下。
状态模式详情参考我的博客:设计模式(二十二)——状态模式(State Pattern)
定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
策略模式的主要优点如下。
其主要缺点如下。
策略模式详情参考我的博客:设计模式(二十三)——策略模式(Strategy Pattern)
把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
优点
缺点
责任链模式详情参考我的博客:设计模式(二十四)——责任链模式(Chain of Responsibility Pattern)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。