全面了解23种设计模式,细说那些被人所知的设计思想。(一周彻底撸完被23种设计模式疯狂折磨)
- 一,设计模式介绍
- 二,设计模式的四大基本要素
- 三,设计模式的七大设计原则
- 四,23种设计模式分为三大类别模式
- 五,创建型模式包含以下 ==5 种模式==。
- 1,[单例(Singleton)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106245567/)
- 2,[原型(Prototype)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106247012/)
- 3,[工厂(Prototype)模式:](https://blog.csdn.net/Crazy_Cw/article/details/103555692/)
- 4,[抽象工厂(AbstractFactory)模式:](https://blog.csdn.net/Crazy_Cw/article/details/103555692/)
- 5,[建造者(Builder)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106482087/)
- 六,结构型模式包含以下 ==7 种模式。==
- 1,[代理(Proxy)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106885466/)
- 2,[适配器(Adapter)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106980667/)
- 3,[桥接(Bridge)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106974925/)
- 4,[装饰(Decorator)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106752477/)
- 5,[外观(Facade)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106910053/)
- 6,[享元(Flyweight)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106843512/)
- 7,[组合(Composite)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106910993/)
- 七,行为型模式分为以下==11种模式。==
- 1,[模板方法(Template Method)模式:]
- 2,[策略(Strategy)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106818217/)
- 3,[命令(Command)模式:]
- 4,[职责链(Chain of Responsibility)模式:](https://blog.csdn.net/Crazy_Cw/article/details/107050678)
- 5,[状态(State)模式:]
- 6,[观察者(Observer)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106819511/)
- 7,[中介者(Mediator)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106984015/)
- 8,[迭代器(Iterator)模式:]
- 9,[访问者(Visitor)模式:]
- 10,[备忘录(Memento)模式:]
- 11,[解释器(Interpreter)模式:](https://blog.csdn.net/Crazy_Cw/article/details/106982499)
一,设计模式介绍
1,简介:
设计模式(英语 design pattern)
,是对面向对象设计中反复出现的问题的解决方案。这个术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。这个术语的含义还存有争议。算法不是设计模式,因为算法致力于解决问题而非设计问题。设计模式通常描述了一组相互紧密作用的类与对象。设计模式提供一种讨论软件设计的公共语言,使得熟练设计者的设计经验可以被初学者和其他设计者掌握。设计模式还为软件重构提供了目标。
随着软件开发社群对设计模式的兴趣日益增长,已经出版了一些相关的专著,定期召开相应的研讨会,而且Ward Cunningham为此发明了WikiWiki用来交流设计模式的经验
2,产生背景:
设计模式
这个术语最初并不是出现在软件设计中,而是被用于建筑领域的设计中。
1977 年
,美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫·亚历山大(Christopher Alexander)在他的著作《建筑模式语言:城镇、建筑、构造(A Pattern Language: Towns Building Construction)中描述了一些常见的建筑设计问题,并提出了 253 种关于对城镇、邻里、住宅、花园和房间等进行设计的基本模式。
1979 年
他的另一部经典著作《建筑的永恒之道》(The Timeless Way of Building)进一步强化了设计模式的思想,为后来的建筑设计指明了方向。
1987 年
,肯特·贝克(Kent Beck)和沃德·坎宁安(Ward Cunningham)首先将克里斯托夫·亚历山大的模式思想应用在 Smalltalk 中的图形用户接口的生成中,但没有引起软件界的关注。
直到 1990 年,软件工程界才开始研讨设计模式的话题,后来召开了多次关于设计模式的研讨会。
1995 年
,艾瑞克·伽马(ErichGamma)
、理查德·海尔姆(Richard Helm)
、拉尔夫·约翰森(Ralph Johnson)
、约翰·威利斯迪斯(John Vlissides)
等 4 位作者合作出版了《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书,在本教程中收录了 23 个设计模式,这是设计模式领域里程碑的事件,导致了软件设计模式的突破。这 4 位作者在软件开发领域里也以他们的“四人组”(Gang of Four,GoF)匿名著称。
3,概念:
设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
4,学习设计模式的意义 :
设计模式的本质
是面向对象设计原则的实际运用,是对类的封装性
、继承性
和多态性
以及类的关联关系
和组合关系
的充分理解。正确使用设计模式具有以下优点。
- 可以提高程序员的思维能力、编程能力和设计能力。
- 使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
- 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
二,设计模式的四大基本要素
1,模式名称(PatternName)
:
每一个模式都有自己的名字,通常用一两个词来描述,可以根据模式的问题、特点、解决方案、功能和效果来命名。模式名称有助于我们理解和记忆该模式,也方便我们来讨论自己的设计。
2,问题(Problem)
:
描述了该模式的应用环境,即何时使用该模式。它解释了设计问题和问题存在的前因后果,以及必须满足的一系列先决条件。
3,解决方案(Solution)
:
包括设计的组成成分、它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象的 组合)来解决这个问题。
4,效果(Consequence)
:
描述了模式的应用效果以及使用该模式应该权衡的问题,即模式的优缺点。主要是对时间和空间的衡量,以及该模式对系统的灵活性、扩充性、可移植性的影响,也考虑其实现问题。显式地列出这些效果对理解和评价这些模式有很大的帮助
三,设计模式的七大设计原则
1,开闭原则
简介:开闭原则(Open Closed Principle,OCP)由勃兰特·梅耶(Bertrand Meyer)提出,他在 1988 年的著作《面向对象软件构造》(Object Oriented Software Construction)中提出:软件实体应当对
扩展开放
,对修改关闭
(Software entities should be open for extension,but closed for modification),这就是开闭原则的经典定义。
作用:
- 可以提高代码的可复用性
- 可以提高软件的可维护性
- 对软件测试的影响
实现方法
可以通过
抽象约束
、封装变化
来实现开闭原则,即通过接口
或者抽象类
为软件实体定义一个相对稳定的抽象层
,而将相同的可变因素封装在相同的具体实现类中。
因为抽象灵活性好,适应性广,只要
抽象的合理
,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
示例
:类图如下:
定义一个接口 Persion (人) , 我需要 女人或者男人(具体的实现)不需要去修改 原来的代码 ,只需要在创建一个子类。这样就非常符合 开闭原则:对扩展开放,对修改关闭。
2,里氏替换原则
简介:里氏替换原则(Liskov Substitution Principle,LSP)由麻省理工学院计算机科学实验室的里斯科夫(Liskov)女士在 1987 年的“面向对象技术的高峰会议”(OOPSLA)上发表的一篇文章《数据抽象和层次》(Data Abstraction and Hierarchy)里提出来的,她提出:
继承必须确保超类所拥有的性质在子类中仍然成立
(Inheritance should ensure that any property proved about supertype objects also holds for subtype objects)。
里氏替换原则主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中蕴含的原理。里氏替换原是继承复用的基础,它反映了基类与子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。
里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
那么如何透明地使用
呢?子类可以改变父类的原有功能
吗?
public class A {
public void fun(int a,int b){
System.out.println(a+b);
}
}
public class B extends A{
@Override
public void fun(int a,int b){
System.out.println(a-b);
}
}
这里本来是加法却修改成了减法,这显然是不符合认知的。
它违背了里氏替换原则,子类改变了父类原有功能后,当我们在引用父类的地方使用其子类的时候,没办法透明使用fun方法了。父类中凡是已经实现好的方法,实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些规范,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。
所以,透明使用的关键就是,子类不能改变父类原有功能。
如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。`
如果程序违背了里氏替换原则,则继承类的对象在基类出现的地方会出现运行错误。这时其修正方法是:取消原来的继承关系,重新设计它们之间的关系。
作用
1,里氏替换原则是实现开闭原则的重要方式之一。
2,它克服了继承中重写父类造成的可复用性变差的缺点。
3,它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
里氏替换原则为良好的继承定义了一个规范:
- 子类必须实现父类的抽象方法,但不得重写父类的非抽象(已实现的)方法。
实现方法
public abstract class Parent{
public void show(int a,int b){
System.out.println(a+b);
}
/**
* 抽象方法,子类实现扩展
*/
public abstract void features();
}
public class Children extends Parent{
public void show(int a,int b){
System.out.println(a+b);
}
@Override
public void features() {
System.out.println("这是子类扩展功能");
}
}
- 子类中可增加自己特有的方法。(可以随时扩展)
- 当子类覆盖或者实现父类的方法时,方法的前置条件(方法形参)要比父类输入参数更加宽松。否则会调用到父类的方法。
public abstract class Parent{
public void setMap(HashMap map){
System.out.println("执行父类setMap方法");
}
}
public class Children extends Parent{
public void setMap(Map map){
System.out.println("执行子类setMap方法");
}
}
public class mainClass {
public static void main(String[] args) {
Children children = new Children();
children.setMap(new HashMap());
}
}
执行结果:
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。否则会调用到父类的方法。
public abstract class Parent{
public abstract List<String> getList();
}
public class Children extends Parent{
//这里返回值类型不对 编译器会报错
//父类返回值是List,子类返回值是List的父类Collection,
//透明使用父类的时候则需要将Collection转换成List。 类向上转换是安全的,向下转换则不一定是安全了
//@Override
// public Collection<String> getList() {
// return new ArrayList<String>();
// }
@Override
public List<String> getList() {
return new ArrayList<String>();
}
}
public class mainClass {
public static void main(String[] args) {
Parent parent = new Children();
parent.setList(new ArrayList<String>());
}
}
我们最好将父类定义为抽象类,并定义抽象方法,让子类重新定义这些方法,当父类是抽象类时候,父类不能实例化
3,依赖倒置原则
4,单一职责原则
5,接口隔离原则
6,迪米特法则
7,合成复用原则
四,23种设计模式分为三大类别模式
1,创建型模式:
它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,不需要知道商品是怎么生产出来一样,因为它们由专门的厂商生产。
2,结构型模式:
它的主要特点是 如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
3,行为型模式:
用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。
五,创建型模式包含以下 5 种模式。
1,单例(Singleton)模式:
简介:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
- 饿汉模式(线程不安全) ,不管客户端需不需要这个对象,都提供了这个对象实例给客户端。
- 懒汉模式(线程不安全), 当客户端需要这个对象时,才会去 新建一个实例提供给客户端。
- 双重检查(懒汉模式上的演变 是线程安全), 用 volatile 修饰 声明对象。(简单来说用它声明的类型变量表示不可以被某些编译器未知的因素更改,可以通过缓存一致性协议保证每个线程都能获得最新值,即满足数据的“可见性”。并且是程度较轻的 synchronized, 所需的编码较少,并且运行时开销也较少), 使用 synchronized 关键字修饰方法(同步代码块时,其他试图访问该方法的线程将被阻塞,直到上一个线程执行完,才执行下一个),用 双重 判断 对象是否为null,检查线程在资源竞争的状态下,出现线程阻塞问题。
- 静态内部类单例模式 (线程安全)。(推荐使用,代码简洁,可读性高,线程安全是因为 java 在创建静态对象的时候已经保证)。
- 枚举单例模式 (代码简单,可读性较差,开发中很少使用,线程安全)
2,原型(Prototype)模式:
简介:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
通过 jdk本身自带接口 (Cloneable) 去实现接口,目标对象是原型对象的一个克隆,不仅仅是具有相同的结构,属性,还与原型对象具有 相同的值。但是 在实例化目标对象,和实例化原型对象后, 在jvm 虚拟机 堆内存里是 两个地址不相同的引用对象。根据对象克隆深度层次的不同,有浅度克隆与深度克隆。
3,工厂(Prototype)模式:
简介:定义一个用于创建产品的接口,由子类决定生产什么产品。
- 工厂(Creator)角色;
- 抽象(Product) 角色;
- 具体产品(Concenter Product) 角色;
4,抽象工厂(AbstractFactory)模式:
简介:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的,抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品具体的情况下,能够创建多个产品对象。
- 抽象工厂模式的核心,任何工厂都必须实现这个接口 (CqwwCallFactroy)
- 具体工厂是抽象工厂的一个实现,负责实例化 (WawaFactroy)
- 具体产品,抽象模式所创建的具体事例对象 (SpecificJapan, SpencificAmerica)
5,建造者(Builder)模式:
简介:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
- 抽象建造者(builder):描述具体建造者的公共接口,一般用来定义建造细节的方法,并不涉及具体的对象部件的创建。
- 具体建造者(ConcreteBuilder):描述具体建造者,并实现抽象建造者公共接口。
- 指挥者(Director):调用具体建造者来创建复杂对象(产品)的各个部分,并按照一定顺序(流程)来建造复杂对象。
- 产品(Product):描述一个由一系列部件组成较为复杂的对象。
六,结构型模式包含以下 7 种模式。
1,代理(Proxy)模式:
简介:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
静态代理:
- subject (抽象主题角色):真实主题与代理主题的共同接口。
- RealSubject(真实主题角色): 定义了代理角色所代表的真实对象
- Proxy(代理主题角色):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真实主题对象之前或者之后执行某些操作,而不是单纯返回真实主题对象。
动态代理:
- 实现InvocationHandler
- invoke : (在代理实例上处理方法调用并返回结果)
- Proxy.newProxyInstance() : 创建代理实例
2,适配器(Adapter)模式:
简介:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
1.类适配器模式, 通过继承实现Adapter
2.对象适配器模式,通过委让实现Adapter
- 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
- 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
- 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
3,桥接(Bridge)模式:
简介:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现的,从而降低了抽象和实现这两个可变维度的耦合度。
- 抽象化(Abstraction)角色:定义抽象类,幷包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
4,装饰(Decorator)模式:
简介:动态地给对象增加一些职责,即增加其额外的功能。
- 抽象组件角色: 一个抽象接口,是被装饰类和装饰类的父接口。
- 具体组件角色:为抽象组件的实现类。
- 抽象装饰角色: 包含一个组件的引用,并定义了与抽象组件一致的接口
- 具体装饰角色:为抽象装饰角色的实现类。负责具体的装饰。
5,外观(Facade)模式:
简介:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
- Facade : 为调用方 定义简单的调用接口。
- Clients : 调用者。通过Facade接口调用提供某功能的内部类群。
- Packages: 功能提供者。指提供功能的类群(模块或子系统)。
6,享元(Flyweight)模式:
简介:运用共享技术来有效地支持大量细粒度对象的复用。
1.内部状态,即不会随着环境的改变而改变的可共享部分。
2.外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。下面来分析其基本结构和实现方法
-
抽象享元角色 Flyweight): 所有具体享元类的父类,规定一些需要实现的公共接口。
-
具体享元角色 (Concrete Flyweight): 抽象享元的具体实现类,并实现了抽象享元角色规定的方法。
-
非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中
享元工厂角色 (Flyweight Factory): 负责创建和管理享元角色。
7,组合(Composite)模式:
简介:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
透明方式实现 (所有的行为,属性,方法都在 抽象接口中, 叶节点和枝节点都必须要实现所有方法)。
安全方式实现 (将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法)。
- Component : (树形结构的节点抽象) :为所有的对象定义统一的接口,(公共属性,行为等的定义,提供管理子节点对象的接口方法
- Leaf : (树形结构的叶节点)
- Composite: (树形结构的枝节点)
七,行为型模式分为以下11种模式。
1,[模板方法(Template Method)模式:]
简介:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
2,策略(Strategy)模式:
简介:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
- Strategy : 策略(算法)抽象。
- ConcreteStrategy :各种策略(算法) 的具体实现
- Contenxt :策略的外部封装类,或者说策略的容器类。根据不同策略执行不同的行为。策略由外部环境决定。
3,[命令(Command)模式:]
简介:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
4,职责链(Chain of Responsibility)模式:
简介:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
优点:
1,降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
2,增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
3,增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
4,责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。,5,责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
1,不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
2,对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
3,职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
结构:
职责链模式主要包含以下角色。
1,抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
2,具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
3,客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
5,[状态(State)模式:]
简介:允许一个对象在其内部状态发生改变时改变其行为能力。
6,观察者(Observer)模式:
简介:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
结构:
观察者 实现 Observer 接口
被观察者,继承 Observble 类。
- Subject (被观察者) :被观察者的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject 需要维持(通知,删除,添加) 一个观察者对象的队列列表。
- ConcreteSubject(被观察者的具体实现):包含一些基本的属性状态及其他操作。
- Observer (观察者,接口或抽象类) : 当Subject 的状态发生变化时,Observer 对象将通过一个 callback函数得到通知。
- ConcreteObserver(观察者的具体实现):得到通知后将完成一些具体的业务逻辑处理。
7,中介者(Mediator)模式:
简介:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
其主要优点如下。
1,降低了对象之间的耦合性,使得对象易于独立地被复用。
2,将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
其主要缺点是:当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护
中介者模式包含以下主要角色。
1,抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
2,具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
3,抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
4,具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
8,[迭代器(Iterator)模式:]
简介:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
9,[访问者(Visitor)模式:]
简介:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
10,[备忘录(Memento)模式:]
简介:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
11,解释器(Interpreter)模式:
简介:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
解释器模式包含以下主要角色:
- 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
- 终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
- 非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
- 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
- 客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。
解析器结构
简易版结构
- Context : 解释器上下文环境类,用来存储解析器的上下文环境,比如需要解释的文法等。
- AbstratctExpression 解释器抽象类。
- ConcreteExpression 解释器具体实现类。