赞
踩
大家好,我是栗筝i,近期我总结梳理了 “GoF”的 23 种设计模式,并使用 Java 对每种设计模式都进行了伪代码与 Demo 实现,并总结了每种设计模式的应用场景,优缺点,UML图等相关内容,字/词数达到了5万,希望对大家有所帮助~~
~
更多 Java 相关内容,大家可以浏览:全网最全的 Java 技术栈内容梳理(持续更新中)
Ps:大家还可以加入我的社区:栗筝i的社区,在更新上我将尽量保证文章的高频、高质、高量,希望大家积极交流监督,让我们共同进步。
1995 年,GoF(Gang of Four,四人组,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人组成)合作出版了 **《Design Patterns: Elements of Reusable Object-Oriented Software》 **一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称【GoF设计模式】。
这 23 种设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性,以及类的关联关系和组合关系的充分理解。
设计模式(Design pattern):是软件开发经验的总结,是软件设计中常见问题的典型解决方案。每个模式都像一个蓝图,您可以自定义以解决代码中的特定设计问题。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
设计模式共分为 3 类模式, 分别为:创建型模式,结构型模式,行为型模式。
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式;
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
实际上,设计模式要干的事情就是解耦。创建型模式是将创建和使用代码解耦,结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦,在下面我们会分别进行详细的介绍。
其中又分为:
设计模式有 7 大原则,目的只有一个:降低对象之间的耦合,增加程序的可复用性、可扩展性和可维护性。
设计原则 | 归纳 | 目的 |
---|---|---|
开闭原则 | 对扩展开放,对修改关闭 | 降低维护带来的新风险 |
里氏替换原则 | 不要破坏继承体系,子类重写方法功能发生改变,不应该影响父类方法的含义 | 防止继承泛滥 |
依赖倒置原则 | 高层不应该依赖低层,要面向接口编程 | 更利于代码结构的升级扩展 |
单一职责原则 | 一个类只干一件事,实现类要单一 | 便于理解,提高代码的可读性 |
接口隔离原则 | 一个接口只干一件事,接口要精简单一 | 功能解耦,高聚合、低耦合 |
迪米特法则 | 不该知道的不要知道,一个类应该保持对其它对象最少的了解,降低耦合度 | 只和朋友交流,不和陌生人说话,减少代码臃肿 |
合成复用原则 | 尽量使用组合或者聚合关系实现代码复用,少使用继承 | 降低代码耦合 |
开闭原则(Open Closed Principle,OCP):软件实体应当对扩展开放,对修改关闭。
实现方法: 通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。
里氏替换原则(Liskov Substitution Principle,LSP):继承必须确保超类所拥有的性质在子类中仍然成立。
里氏替换原则是继承复用的基础,它反映了基类与子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
对里氏替换原则的定义可以总结如下 4 点:
依赖倒置原则(Dependence Inversion Principle,DIP)有 2条 原则:
高层模块不应该依赖低层模块,两者都应该依赖其抽象;
抽象不应该依赖细节,细节应该依赖抽象。
核心思想是:要面向接口编程,不要面向实现编程, 降低类间的耦合性。
依赖倒置原则的主要作用如下:
依赖倒置原则的实现方法:
单一职责原则(Single Responsibility Principle,SRP)单一功能原则:规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
接口隔离原则(Interface Segregation Principle,ISP)要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。
接口隔离原则定义:客户端不应该被迫依赖于它不使用的方法,一个类对另一个类的依赖应该建立在最小的接口上。
接口隔离原则的实现方法,在具体应用接口隔离原则时,应该根据以下几个规则来衡量:
迪米特法则(Law of Demeter,LoD)又叫作最少知识原则,只与你的直接朋友交谈,不跟“陌生人”说话。其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。
在运用迪米特法则时要注意以下 6 点:
合成复用原则(Composite Reuse Principle,CRP)又叫组合/聚合复用原则(Composition/Aggregate Reuse Principle,CARP)。它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范
工厂方法是一种十分常用的创建型设计模式,它在父类中提供了创建对象的接口但允许子类更改将要创建的对象的类型。
在一些情况下,要创建的对象需要一系列复杂的初始化操作,比如查配置文件、查数据库表、初始化成员对象等,如果把这些逻辑放在构造函数中,会极大影响代码的可读性。不妨定义一个类来专门负责对象的创建,这样的类就是工厂类,这种做法就是工厂模式,在任何需要生成复杂对象的地方,都可以使用工厂模式。
一般情况下,我们所提及的 “工厂模式” 会被细分为三种,即简单工厂、工厂方法和抽象工厂。而 《GoF 的设计模式》一书中,它将简单工厂模式看作是工厂方法模式的一种特例,所以工厂模式只被分成了工厂方法和抽象工厂两类。
# 关于 简单工厂模式
简单工厂模式(Smiple Factory Pattern):定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类,简单工厂模式也被称为静态工厂模式。
简单工厂模式将产品的“消费”和“生产”完全分开,调用房,只需要自己需要什么产品,和如何使用就可以了,而对于产品的具体生产任务,则由工厂类来实现。
简单工厂模式的详细内容可以参照:【详解设计模式-简单工厂模式 : https://lizhengi.blog.csdn.net/article/details/128043083】
# 关于 工厂方法模式
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过工厂父类定义负责创建产品的公共接口,子类负责生产具体对象。可以理解为简单工程模式的升级,解决简单工厂模式的弊端。
如果在简单工厂模式中,扩增具体产品信息,需要对原有工厂进行改造,当需求的产品类别增加到一定程度时,工厂较负责的产品线也相对复杂,当出现问题时,所有的产品的生产将会中断。工厂方法模式 解决简单工厂模式的弊端,实现父类定义公共实现接口,子类负责实现创建具体的对象,这样就可以实现增加产品类时,不需要修改工厂类,而只需要修改工厂子类。
工厂方法模式的详细内容可以参照:【详解设计模式-工厂方法模式 : https://lizhengi.blog.csdn.net/article/details/128050174】
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。这里的抽象角色就是产品族。Ps:产品族是具有相同属性的同类型产品。
抽象工厂,非常适合解决两个维度的组合产品的构造问题,取其中一个维度作为产品族,另外一个维度作为产品族中具体的多个产品。
抽象工厂模式的详细内容可以参照:【详解设计模式-抽象工厂模式 : https://lizhengi.blog.csdn.net/article/details/128055856】
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在单例模式中,内存中只会创建且仅创建一次对象在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
Ps:在 Spring 中,每个 Bean 默认就是单例的,这样的优点是 Spring 容器可以管理这些 Bean 的生命周期,决定什么时候创建出来,什么时候销毁,销毁的时候如何处理等等。
单例模式有两种类型:
单例模式的详细内容可以参照:【详解设计模式-单例模式 : https://lizhengi.blog.csdn.net/article/details/128061347】
建造者模式(Builder Pattern)也叫做生成器模式,是 GoF 的 23 种设计模式的一种,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
当我们需要实列化一个复杂的类,以得到不同结构类型和不同的内部状态的对象时,我们可以用不同的类对它们的实列化操作逻辑分别进行封装,这些类我们就称之为建造者。
当我们需要来自同一个类,但是要就有不同结构对象时,就可以通过构造另一个建造者来进行实列化。
建造者(Builder)模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定,所以它通常在以下场合使用。
建造者模式的详细内容可以参照:【详解设计模式-建造者模式 : https://lizhengi.blog.csdn.net/article/details/128067131】
原型模式(Prototype Pattern) ,是 GoF 的 23 种设计模式的一种,是用于创建重复的对象,同时又能保证性能。属于创建型模式,提供创建对象的最佳方式。
原型(Prototype),在制造业中通常是指大批量生产开始之前研发出的概念模型,并基于各种参数指标对其进行检验,如果达到了质量要求,即可参照这个原型进行批量生产。原型模式达到以原型实例创建副本实例的目的即可,并不需要知道其原始类,也就是说,原型模式可以用对象创建对象,而不是用类创建对象,以此达到效率的提升。
原型模式的使用需要注意浅拷贝与深拷贝的问题:
原型模式的详细内容可以参照:【详解设计模式-原型模式 : https://lizhengi.blog.csdn.net/article/details/128075439】
适配器模式(Adapter Pattern)又称为变压器模式,是 GoF 的 23 种设计模式中的一种结构型设计模式。
适配器模式 的功能是将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而导致无法在一起工作的两个类能够一起工作。
适配器模式的详细内容可以参照:【详解设计模式-适配器模式 : https://lizhengi.blog.csdn.net/article/details/128085445】
装饰器模式(Decorator Pattern)也称为包装模式(Wrapper Pattern),是 GoF 的 23 种设计模式中的一种结构型设计模式。
装饰器模式 是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能)。
装饰器模式 的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能
装饰器模式的详细内容可以参照:【详解设计模式-装饰器模式 : https://lizhengi.blog.csdn.net/article/details/128092556】
代理模式(Proxy Pattern),Java 常见的设计模式之一,是 GoF 的 23 种设计模式中的一种结构型设计模式。
代理模式 是指客户端并不直接调用实际的对象,而是通过调用代理对象,来间接的调用实际的对象。代理对象 具备真实对象的功能,并代替真实对象完成相应操作,并能够在操作执行的前后,对操作进行增强处理(为真实对象提供代理,然后供其他对象通过代理访问真实对象)。
代理模式的详细内容可以参照:【详解设计模式-代理模式 : https://lizhengi.blog.csdn.net/article/details/128103046】
外观模式(Facade Pattern),又称为门面模式,是 GoF 的 23 种设计模式中的一种结构型设计模式。
外观模式 是指提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口。使得子系统更容易使用。使用外观模式时,我们创建了一个统一的类,用来包装子系统中一个或多个复杂的类,客户端可以直接通过外观类来调用内部子系统中方法,从而外观模式让客户和子系统之间避免了紧耦合。
外观模式 的本质是:封装交互,简化调用。
外观模式的详细内容可以参照:【详解设计模式-外观模式 : https://lizhengi.blog.csdn.net/article/details/128110295】
桥接模式(Bridge Pattern)也称为桥梁模式、接口模式或者柄体模式,有点像适配器模式,也是 GoF 的 23 种设计模式中的一种结构型设计模式。
桥接模式 是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。
桥接模式的详细内容可以参照:【详解设计模式-桥接模式 : https://lizhengi.blog.csdn.net/article/details/128119591】
组合模式(Composite Pattern),又叫部分整体模式,是 GoF 的 23 种设计模式中的一种结构型设计模式。
组合模式 是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。它创建了对象组的树形结构。
组合模式的详细内容可以参照:【详解设计模式-组合模式 : https://lizhengi.blog.csdn.net/article/details/128127215】
享元模式(Flyweight Pattern),是对象池的一种体现,也是 GoF 的 23 种设计模式中的一种结构型设计模式。
享元模式 主要用于减少创建对象的数量,以减少内存占用和提高性能。它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式 尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
享元模式的详细内容可以参照:【详解设计模式-享元模式 : https://lizhengi.blog.csdn.net/article/details/128136268】
策略模式(Strategy Pattern)也被称为政策模式(Policy Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
策略模式 是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,使得它们可以互换,被封装起来的算法具有独立性外部不可改变其特性。
策略模式 在实际的项目开发中,这个模式也比较常用。最常见的应用场景是,利用它来避免冗长的 if-else 或 switch 分支判断。不过,它的作用还不止如此。它也可以像模板模式那样,提供框架的扩展点等等。
策略模式的详细内容可以参照:【详解设计模式-策略模式 : https://lizhengi.blog.csdn.net/article/details/128143313】
观察者模式(Observer Pattern)也被称为发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式,是在 GoF 23 种设计模式中定义了的行为型模式。
观察者模式 定义了一对多的关系,让多个观察者对象同时监听某一个主体对象,这个主体对象发生变化时就会通知所有的观察者对象,使得他们能够自己更新自己。
观察者模式的特点:
被观察者不知道具体的观察者是谁,只知道自己被观察了,并且在合适的时机进行广播,让感兴趣的观察者知道发生了什么事情;
观察者依赖于被观察者,被观察者不依赖于观察者,是单向关系,耦合程度不高。没有被观察者,观察者无法工作;没有观察者,被观察者该干啥干啥,因为被观察者本来就不清楚谁观察他,发广播是被观察的个人行为;
通常被观察者出现行为上的变化,需要观察者做出反馈。显然一般情况下观察者并不知道被观察者啥时候会有变化,因此该反馈是一种被动反馈,实现的是一种回调机制。
观察者模式的详细内容可以参照:【详解设计模式-观察者模式 : https://lizhengi.blog.csdn.net/article/details/128152116】
模板方法模式(Template Method Pattern)也被称为模板模式(Template Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
模板方法模式 定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式 核心:处理某个流程的代码已经都具备,但是其中某个节点的代码暂时不能确定。因此,我们采用模版方法模式,将这个节点的代码实现转移给子类完成。即:处理步骤在父类中定义好,具体的实现延迟到子类中定义
模板方法模式的详细内容可以参照:【详解设计模式-模板方法模式 : https://lizhengi.blog.csdn.net/article/details/128159860】
迭代器模式(Iterator Pattern)也被称为游标模式(Cursor Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。是一种最简单也最常见的设计模式。
迭代器模式 可以让用户透过特定的接口巡访容器中的每一个元素而不用了解底层的实现。
迭代器模式 提供一种方法顺序访问一个聚合(指一组对象的组合结构,如:Java中的集合、数组等)对象中各个元素,而又不需暴露该对象的内部表示。迭代器模式的本质:控制访问聚合对象中的元素。其设计意图:无须暴露聚合对象的内部实现,就能够访问到聚合对象中的各个元素。
迭代器模式的详细内容可以参照:【详解设计模式-迭代器模式 : https://lizhengi.blog.csdn.net/article/details/128164451】
首先它可以对同一模块中有先后执行顺序要求的类或对象进行成链,以达到高聚合的目的。同时对于单一执行状态下的执行步骤,可以通过非状态模式的成链方式进行组装,便可以实现改变执行顺序的目的,让代码维护性变高。
责任链模式(Chain of Responsibility Pattern)也被称为职责链模式,是在 GoF 23 种设计模式中定义了的行为型模式。
责任链模式 是将链中的每一个节点看作是一个对象,每个节点处理的请求不同,且内部自动维护一个下一节点对象。当一个请求从链式的首段发出时,会沿着链的路径依此传递给每一个节点对象,直至有对象处理这个请求为止。
责任链模式 将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
责任链模式的详细内容可以参照:【详解设计模式-责任链模式 : https://lizhengi.blog.csdn.net/article/details/128171017】
命令模式(Command Pattern)也被称为行动模式(Action Pattern)、事物模式(Transaction Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
命令模式 是一种数据驱动的设计模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。命令是对命令的封装,每一个命令都是一个操作,请求方发出请求,接收方接收请求,并执行操作。命令模式解耦了请求方和接收方。
命令模式的详细内容可以参照:【详解设计模式-命令模式 : https://lizhengi.blog.csdn.net/article/details/128176316】
备忘录模式(Memento Pattern)也被称为快照模式(Snapshot Pattern)、Token 模式(Token Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
备忘录模式 会保存一个对象的某个状态,以便在适当的时候恢复对象。
备忘录模式 在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
备忘录模式的详细内容可以参照:【详解设计模式-备忘录模式 : https://lizhengi.blog.csdn.net/article/details/128181875】
状态模式(State Pattern)也被称为状态机模式(State Machine Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
在状态模式 类的行为是基于它的状态改变的。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。状态模式 对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
状态模式的详细内容可以参照:【详解设计模式-状态模式 : https://lizhengi.blog.csdn.net/article/details/128191135】
访问者模式(Visitor Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。据《大话设计模式》中说算是最复杂也是最难以理解的一种模式了。
访问者模式 是一种将数据操作与数据结构分离的设计模式,它可以算是 23 中设计模式中最复杂的一个,但它的使用频率并不是很高,大多数情况下,你并不需要使用访问者模式,但是当你一旦需要使用它时,那你就是需要使用它了。
访问者模式 的基本想法是,软件系统中拥有一个由许多对象构成的、比较稳定的对象结构,这些对象的类都拥有一个 accept 方法用来接受访问者对象的访问。访问者是一个接口,它拥有一个 visit 方法,这个方法对访问到的对象结构中不同类型的元素做出不同的处理。在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施 accept 方法,在每一个元素的 accept 方法中会调用访问者的 visit 方法,从而使访问者得以处理对象结构的每一个元素,我们可以针对对象结构设计不同的访问者类来完成不同的操作,达到区别对待的效果。
访问者模式 适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。
访问者模式的详细内容可以参照:【详解设计模式-访问者模式 : https://lizhengi.blog.csdn.net/article/details/128197861】
中介者模式(Mediator Pattern)也被称为调停者模式,是在 GoF 23 种设计模式中定义了的行为型模式。
中介者模式 是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。
中介者模式 的核心在于中介者类的引入,在中介者模式中,中介者类承担了两方面的职责 (所有对象之间的交互都 在 Mediator 类中进行):
中介者模式的详细内容可以参照:【详解设计模式-中介者模式 : https://lizhengi.blog.csdn.net/article/details/128208282】
解释器模式(interpreter pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
解释器模式 这种模式被用在 SQL 解析、符号处理引擎等。
解释器模式 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。
解释器模式的详细内容可以参照:【详解设计模式-解释器模式 : https://lizhengi.blog.csdn.net/article/details/128213942】
设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。我们用设计原则来评判代码设计哪里有问题,然后再通过具体的设计模式来改善。
设计模式的目的是为了代码更加的优雅、易维护、易扩展
设计模式相较于其他的知识,是稍微简单易学的,但是也十分容易被滥用(应用设计模式会提高代码的可扩展性,但同时也会带来代码可读性的降低),因此我们需要注意的是,有些场景十分真的需要使用一些设计模式,而不是使它们被过度滥用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。