目录
1、设计模式汇总一览表
2、创建型设计模式详细介绍
(1)单例模式(Singleton)
(2)抽象工厂模式(AbstractFactory)
(3)原型模式(Prototype):深克隆、浅克隆
(4)建造者模式(Builder)
(5)FactoryMethod工厂方法模式
3、结构型模式详细介绍
(1)外观模式(Facade)
(2)桥接模式(Bridge)
(3)组合模式(Composite)
(4)享元模式(Fly weight Pattern)
(5)代理模式(Proxy)
(6)适配器模式(Adapter)
(7)装饰模式(Decorator)
4、行为型模式详细介绍
(1)观察者模式(Observer)
(2)迭代器模式(Iterator)
(3)模板方法模式(Template Method)
(4)策略模式(Strategy)
(5)责任链模式(Chain of Responsibility)
(6)命令模式(Command)
(7)解释器模式(Interpreter)
(8)访问者模式(Visitor)
(9)中介者模式(Mediator)
(10)备忘录模式(Memento)
(11)状态模式(State)
设计模式(DesignPattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
创建型 模式
|
用于创建对象
|
共5种 ——背诵口诀 :
单抽元件(建)厂
|
结构型 模式
|
处理类或对象的组合
|
共7种 —— 背诵口诀 :
外侨(桥)组员(元)戴(代)配饰。
|
行为型 模式
|
描述类与对象怎样交互、怎样分配职责
|
共11种 —— 背诵口诀 :
观摩(模)对(迭)策,
责令解放(访),
戒(介)忘台(态)。
|
设计模式为什么要分为创建型、结构型、行为型?
设计模式按照功能和用途可以分为创建型、结构型和行为型三种类型,这种分类方式主要是为了方便设计模式的理解和应用。
创建型模式:创建型模式主要关注对象的创建过程,包括如何创建对象、如何组合和表示对象等。创建型模式包括单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式等。通过创建型模式,可以更加灵活地创建和组合对象,同时也可以隐藏对象的创建细节,提高代码的复用性和可维护性。
结构型模式:结构型模式主要关注对象的组成和关系,包括如何将类和对象组合成更大的结构,以及如何简化对象之间的交互。结构型模式包括适配器模式、装饰器模式、代理模式、组合模式、桥接模式、外观模式和享元模式等。通过结构型模式,可以更好地组织代码,使得代码更加清晰和易于理解,同时也可以提高代码的重用性和可维护性。
行为型模式:行为型模式主要关注对象之间的交互和通信,包括如何定义对象的职责和行为,以及如何协调不同对象之间的工作。行为型模式包括模板方法模式、策略模式、命令模式、责任链模式、状态模式、观察者模式、中介者模式和访问者模式等。通过行为型模式,可以更好地解耦对象之间的依赖关系,使得代码更加灵活和可扩展,同时也可以提高代码的可读性和可维护性。
总之,设计模式按照功能和用途的不同进行分类,有助于我们更好地理解和应用它们,同时也有助于我们选择合适的设计模式来解决具体的问题。
目的 | 设计模式 | 简要说明 | 可改版的方面 |
创 建 型 |
Singleton
单例
|
保证一个类仅有一个实例 ,并提供一个访问它的全局访问点。
|
类的单个实例
|
Abstract Factory
抽象工厂
|
提供一个创建一系列相关或相互依赖对象的 接口 ,而 无需指定它们具体的类 。
|
产品对象族
|
|
Prototype
原型
|
用原型实例 指定创建对象的种类 ,并且通过拷贝这个原型来创建新的象。
|
实例化类的对象
|
|
Builder
建造者
|
将一个复杂的对象的 构建与它的表示分离 ,使得 同样的构建 过程可以创建 不同的表示 。
|
如何建立一个组合对象
|
|
Abstract Method
工厂方法
|
定义一个用于创建对象的 接口 ,让 子类决定将哪一个类实例化 。使一个类的实例化延迟到其子类。
|
实例化子类对象
|
单例模式(Singleton)确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通常用于控制资源的访问,例如数据库连接或线程池。
单例模式的核心是一个静态变量,用于存储类的唯一实例。这个变量必须是私有的,并且必须在类内部实例化。类的构造函数必须是私有的,以确保只能在类内部创建实例。最后,类必须提供一个公共的静态方法,用于访问实例。下面是类图示例:
抽象工厂模式提供了一种创建一组相关或相互依赖对象的方法,而无需指定它们的具体类。抽象工厂模式通过将对象的创建委托给工厂对象来实现这一点,这些工厂对象负责实例化具体类的对象。
抽象工厂模式的核心是抽象工厂接口和具体工厂类。抽象工厂接口定义了一组用于创建一组相关对象的抽象方法。具体工厂类实现抽象工厂接口,并实现这些方法来创建具体的对象。客户端代码只需要使用抽象工厂接口来创建对象,而无需关心具体的实现。下面是类图示例:
原型模式提供了一种通过克隆现有对象来创建新对象的方法。原型模式基于一个已经存在的对象,通过对其进行复制来创建新的对象,而不是通过实例化一个类来创建对象。
在原型模式中,我们首先定义一个原型接口或者抽象类,该接口或抽象类定义了用于克隆自身的方法。然后,我们实现一个或多个具体的原型类,这些类实现了原型接口或抽象类,并重写了克隆方法以实现对象的复制。
建造者模式通过将对象构建过程分解为一系列步骤来创建复杂对象。该模式允许我们使用相同的构建过程来创建不同类型的对象。
在建造者模式中,我们定义一个抽象建造者类,该类定义了用于构建复杂对象的一组抽象方法。然后,我们实现一个或多个具体的建造者类,这些类实现了抽象建造者类中定义的方法,并提供了一种用于构建特定类型对象的构建过程。最后,我们定义一个指导者类,该类使用抽象建造者类中的方法来控制构建过程,并将最终的对象返回给客户端。下面是类图示例:
工厂方法模式提供了一种将对象的创建委托给子类的方式。在工厂方法模式中,我们定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法将对象的实例化延迟到子类中,从而使得客户端代码在不必指定具体类的情况下,创建了一个特定类的实例。
在工厂方法模式中,通常会定义一个抽象的工厂类,其中包含了一个抽象的工厂方法,该方法返回一个产品的抽象接口。具体的产品类将会实现该抽象接口,并在工厂方法中返回相应的实例。下面是类图示例:
目的 | 设计模式 | 简要说明 | 可改版的方面 |
结 构 型 |
Facade
外观模式
|
为子系统中的一组接口提供一个一致的界面 ,外观模式通过提供一个高层接口,隔离了外部系统与子系统间复杂的交互过程,使得复杂系统的子系统更易使用。
|
与子系统的接口
|
Bridge
桥接
|
将抽象部分与它的实现部分分离 ,使它们都可以独立地变化。
|
对象的实现
|
|
Composite
组合模式
|
将对象组合成树形结构以表示“ 部分-整体 ”的层次结构。
Composite使得客户对单个对象和复合对象的使用具有一致性。
|
对象的结构和组合
|
|
Fly weight Pattern
享元模式
|
运用 共享技术 有效地支持大量 细粒度 的对象。
|
对象的存储代价
|
|
Proxy
代理模式
|
为其他对象提供一种代理以控制对这个对象的问。
代理模式使用代理对象完成用户请求, 屏蔽用户对真实对象的访问 。
|
如何访问对象对象位置
|
|
Adapter (类)
适配器
|
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类,可以一起工作。 |
与对象的接口
|
|
Decorator
装饰模式
|
动态地给一个对象添加一些额外的职责 。就扩展功能而言,Decorator模式比生成子类方式更为活。
|
无子类对象责任
|
外观模式为子系统中的一组接口提供了一个统一的接口,以简化客户端与子系统之间的交互。外观模式提供了一个高层次的接口,以便客户端可以更方便地使用子系统的功能。
在外观模式中,我们定义了一个外观类,该类封装了子系统中的一组接口。客户端代码只需要与外观类进行交互,而不需要直接与子系统的接口进行交互。外观类负责将客户端请求委托给适当的子系统对象进行处理,并返回结果给客户端。下面是类图示例:
桥接模式将抽象部分与实现部分分离开来,以便它们可以独立地变化。桥接模式通过创建一个桥接接口来实现这一目的,该接口将抽象部分和实现部分分离开来,使得它们可以独立地进行变化。
在桥接模式中,我们首先定义了一个抽象接口,该接口定义了一组抽象方法,用于表示需要实现的功能。然后,我们定义了一个实现接口,该接口实现了抽象接口,并提供了具体的实现。最后,我们创建一个桥接接口,该接口将抽象接口和实现接口结合在一起,以便它们可以进行交互。下面是类图示例:
组合模式允许我们将对象组合成树形结构来表示“整体/部分”层次结构。组合模式将对象分为两个类型:叶节点和组合节点。叶节点表示单个对象,而组合节点表示由多个对象组成的组合。
在组合模式中,我们首先定义了一个抽象基类,该类定义了一组共同的操作,用于表示组合中的对象。然后,我们定义了两个子类:叶节点和组合节点。叶节点表示单个对象,而组合节点表示由多个对象组成的组合。
享元模式旨在通过共享尽可能多的数据来最小化内存使用和对象创建。它适用于需要创建大量类似对象的场景,其中对象之间的区别仅在于它们的内部状态。
在享元模式中,我们通过将对象分为内部状态和外部状态两部分来最小化内存使用和对象创建。内部状态是对象可共享的状态,而外部状态是随对象变化而变化的状态。
享元模式的核心思想是缓存对象。在第一次创建对象时,我们将其存储在缓存中。在之后需要相同对象时,我们从缓存中获取它们,而不是重新创建它们。
代理模式允许我们为其他对象提供一个替代品或占位符,以控制对这个对象的访问。它适用于需要控制对某个对象的访问时,例如在访问某个重要对象时需要进行权限检查。
在代理模式中,我们定义了一个代理类,它充当了客户端和实际对象之间的中介。代理类保存了一个对实际对象的引用,并提供了与实际对象相同的接口,以便客户端可以通过代理访问实际对象。在客户端请求时,代理类会拦截请求,并在实际对象执行请求之前进行某些操作,例如权限检查或缓存数据等。
适配器模式允许我们将不兼容的对象接口转换为客户端需要的接口,以便它们可以在一起工作。适配器模式的目的是使原本不兼容的接口可以协同工作,而无需修改它们的源代码。
在适配器模式中,我们定义了一个适配器类,它实现了客户端所需要的目标接口,并将实际对象的接口转换为目标接口。适配器类保存了一个对实际对象的引用,并通过在目标接口和实际对象接口之间进行转换,使它们可以进行交互。
适配器模式有两种实现方式:类适配器和对象适配器。类适配器使用多重继承来适配接口,而对象适配器使用组合来适配接口。类适配器适配器适用于适配一个类的接口,而对象适配器适用于适配一个对象的接口。
装饰模式允许我们在不改变现有对象的情况下,动态地向其添加行为。装饰模式通过将对象放入包装器中来实现这一目的,同时保持包装器接口与原始对象接口相同。
在装饰模式中,我们定义了一个装饰器基类和一个具体组件类。装饰器基类实现了与组件相同的接口,并将组件对象作为其成员变量。具体装饰器类继承自装饰器基类,并在其成员变量上添加额外的功能。
通过使用装饰模式,我们可以将多个装饰器链式地链接在一起,以便实现复杂的行为。由于装饰器模式是基于组合而非继承的,因此它可以动态地添加或删除行为,而无需更改原始对象的代码。
目的 | 设计模式 | 简要说明 | 可改版的方面 |
行 为 型 |
Observer
观察者模式
|
观察者模式 定义了对象间的一种一对多依赖关系 ,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
|
信赖于另一对象的对象数量,信对象如何保持最新数据
|
Template Method
模板方法
|
定义一个操作中的算法的骨架 ,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个
算法的结构即可重定义该算法的某些特定步骤。
|
算法的步骤
|
|
Iterator
迭代器模式
|
提供一种方法顺序访问一个聚合对象中各个元素, 而又 无须暴露该对象的内部表示 。
|
如何访问、遍历聚集的元素
|
|
Strategy
策略模式
|
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模
式 让算法独立于使用它的客户而独立变化 。
|
算法
|
|
Chain of Responsibility
责任链模式
|
避免请求发送者与接收者耦合在一起 ,让多个对象都有可能接收请求,将这些对象连接成一条链并且沿着这条链传递请求,直到有对象处理它为止。
|
可满足请求的对象
|
|
Command
命令模式
|
将一个请求封装成一个对象,从而使得用不同的请求对客户进行参数化;对请求排队或 记录请求日志 ,以及 支持可撤销的操作 。
|
何时及如何满足一个请求
|
|
Interpreter
解释器模式
|
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来 解释语言中的句子 。
|
语言的语法和解释
|
|
Visitor
访问者模式
|
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作
用与这些元素的新操作。即对于某个对象或者一组对象, 不同的访问者,产生的结果不同 ,执行
操作也不同。
|
无须改变其类而可应用于对象的操作
|
|
Mediator
中介者模式
|
用一个中介对象来封装一系列的对象交互, 中介者使各对象不需要显式地相互引用 ,从而使其耦合松散,而且可以独立地改变它们之间的交互。
|
对象之间如何交互以及哪些对象交互
|
|
Memento
备忘录模式
|
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态。
|
何时及哪些私有信息存储在对象之外
|
|
State
状态模式
|
允许一个对象在其内部状态改变时改变它的行为 。对象看起来似乎修改了它的类。
|
对象的状态
|
观察者模式允许对象之间建立一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖对象都将得到通知并自动更新。
在观察者模式中,有两种类型的对象:观察者和被观察者。被观察者维护了一个观察者列表,并提供了用于添加、删除和通知观察者的接口。观察者定义了接收通知并响应的方法。
当被观察者状态发生改变时,它将遍历其观察者列表并调用每个观察者的更新方法。观察者的更新方法将执行响应的操作以响应被观察者状态的变化。
迭代器模式提供一种方法访问一个容器对象中的各个元素,而又不需要暴露该对象的内部表示。通过使用迭代器模式,可以支持对容器中的元素进行多种遍历操作,如顺序遍历、倒序遍历、部分遍历等。
在迭代器模式中,有两个主要的对象:迭代器和容器。容器负责维护元素集合,并提供用于获取迭代器的接口。迭代器负责遍历容器中的元素,并提供用于判断是否还有下一个元素、获取当前元素等操作的接口。
模板方法模式定义了一个操作中的算法框架,而将一些步骤延迟到子类中实现。模板方法模式使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法模式由抽象类和具体实现类组成。抽象类定义了一个模板方法,该方法定义了算法的框架,并规定了一些基本方法和抽象方法。具体实现类实现了抽象类中的抽象方法,并可以重写基本方法,但不能重写模板方法。
策略模式定义了一系列算法(策略),并将其封装成独立的对象,使得它们可以在不同的上下文中互换使用,从而使得算法的变化独立于使用算法的客户。
在策略模式中,有三个主要的对象:策略接口、具体策略类和上下文对象。策略接口定义了一组算法操作的接口,具体策略类实现了策略接口中的算法操作,而上下文对象则维护了一个策略对象的引用,并将具体的算法操作委托给策略对象来执行。
责任链模式允许将请求沿着处理链进行传递,直到其中某个处理者能够处理它为止。在责任链模式中,请求被沿着一条链传递,每个处理者都有机会来处理请求,或将请求传递给下一个处理者。
在责任链模式中,有三个主要的对象:抽象处理者、具体处理者和客户端。抽象处理者定义了处理请求的接口,具体处理者实现了抽象处理者的接口,并负责处理请求或将请求传递给下一个处理者,而客户端则创建处理链并将请求发送到处理链的起始点。
命令模式允许将请求封装为对象,从而使得可以将请求参数化、将请求放入队列中、记录请求日志、提供可撤销操作等。在命令模式中,将请求发送者和请求接收者解耦,使得它们不需要知道彼此的存在,而是通过命令对象进行通信。
在命令模式中,有四个主要的对象:抽象命令、具体命令、命令接收者和命令发送者。抽象命令定义了命令的接口,具体命令实现了抽象命令的接口,并包含了命令接收者的引用,命令接收者实现了具体命令所定义的操作,而命令发送者创建具体命令并将其发送给命令接收者。
解释器模式提供了一种定义语言文法并解释语法的方式。在解释器模式中,我们定义一种语言的文法,并且实现一个解释器,用来解释语言中的表达式。
在解释器模式中,我们通常有以下三种角色:
抽象表达式(Abstract Expression):定义了一个抽象的接口,用于解释语法规则中的终结符和非终结符。
终结符表达式(Terminal Expression):实现了抽象表达式接口,并定义了一个终结符的解释操作。
非终结符表达式(Nonterminal Expression):实现了抽象表达式接口,并定义了一个非终结符的解释操作,它通常由多个终结符和非终结符组成。
在解释器模式中,我们将整个语言都看作一个抽象语法树,每一个节点都是一个表达式,而每一个叶子节点都是终结符表达式,每一个非叶子节点都是非终结符表达式。当我们需要解释一段语言时,我们只需要将这段语言转化成抽象语法树,并按照树的结构进行解释即可。
访问者模式能够将算法与数据结构分离开来。访问者模式的核心思想是:在不改变数据结构的前提下,增加新的操作。
在访问者模式中,我们通常有以下两种角色:
抽象访问者(Abstract Visitor):定义了对数据结构中的元素进行操作的方法。
具体访问者(Concrete Visitor):实现了抽象访问者接口,并且提供了具体的操作逻辑。
在访问者模式中,我们还需要定义两个角色:
抽象元素(Abstract Element):定义了一个接口,用于访问者访问该元素。
具体元素(Concrete Element):实现了抽象元素接口,并且提供了接受访问者访问的方法。
在访问者模式中,访问者对象将会遍历整个数据结构,并且依次访问每一个元素。当访问者访问到一个元素时,它会根据具体元素的类型来调用相应的操作方法。由于访问者模式将数据结构和操作分离开来,因此我们能够在不改变数据结构的前提下,增加新的操作,这样就提高了代码的可扩展性和可维护性。
中介者模式通过将对象之间的交互委托给中介者对象来减少对象之间的直接耦合。中介者模式的核心思想是通过将对象之间的复杂关系转化为中介者对象和各个对象之间的简单关系,从而提高系统的灵活性和可维护性。
在中介者模式中,有一个中介者对象,它封装了一些处理对象之间交互的逻辑。各个对象可以通过中介者对象来交互,而不是直接与其他对象交互。当某个对象需要与其他对象进行通信时,它会向中介者对象发送请求,中介者对象会将请求转发给其他对象,然后将响应返回给请求对象。
中介者模式的主要优点是它能够减少对象之间的耦合,从而提高系统的灵活性和可维护性。它还能够将复杂的对象之间的交互关系转化为中介者对象和各个对象之间的简单关系,使得系统更加易于理解和维护。主要缺点是中介者对象可能会变得复杂和难以维护,因为它需要处理大量的对象之间的交互。
备忘录模式允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。备忘录对象是用来保存其他对象的内部状态,并在需要的时候恢复该状态。
备忘录模式通常由三个主要组件组成:Originator(原发器),Memento(备忘录)和Caretaker(管理者)。Originator是要保存和恢复状态的对象,Memento是用于存储状态的对象,Caretaker是用于管理Memento的对象。
在备忘录模式中,Originator创建Memento对象,将其内部状态复制到该对象中,然后将该对象传递给Caretaker进行管理。当需要恢复状态时,Caretaker将Memento对象传递给Originator,Originator从该对象中提取状态并将其应用于自身。
备忘录模式的主要优点是它允许在不影响对象的封装性的情况下保存和恢复状态。它还提供了一种方法来撤销操作,因为它允许将对象返回到之前的状态。主要缺点是它可能会占用大量内存,特别是在需要保存大量状态的情况下。
状态模式允许对象在其内部状态发生改变时改变其行为。状态模式的核心思想是将对象的状态封装在单独的类中,使得对象能够在运行时根据不同状态执行不同的行为。
状态模式通常由三个主要组件组成:Context(上下文),State(状态)和ConcreteState(具体状态)。Context是包含状态对象的主体,它提供了一些用于操作状态对象的接口。State是一个抽象基类,它定义了一些用于操作状态的方法。ConcreteState是继承自State的具体状态类,它实现了State定义的方法。
在状态模式中,当一个对象的状态发生改变时,它将调用Context对象的方法,然后Context对象将请求转发给当前的状态对象,状态对象然后执行相应的操作。当状态发生改变时,Context对象将将其当前状态切换到新状态。
状态模式的主要优点是它能够减少重复的代码,同时也能提高代码的可维护性和可扩展性。它还能够消除一些条件语句,使得代码更加清晰和易于理解。主要缺点是它可能会增加类的数量,并且可能会导致对象的行为变得复杂和难以理解。
附:《设计模式》