本人在进入软件行业开始就不断地从不同的途径不同的方式接触设计模式的相关方面,也在2019年对设计模式进行详细的解读以及参考相关资料整合出自己的理解以及给出了相关的实现实例,两年时间过去了,在此再次进行汇总整合,希望能有所更深的理解、同时给读者以参考。文中不免疏漏之处,望读者不吝指教,不胜感激!
1. 设计模式介绍
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的,能够用来提高代码可复用性、可维护性、可读性、稳健性以及安全性等。
面向对象软件设计原则
(1)开闭原则:
软件实体应当对扩展开放,对修改关闭;
(2)里氏替换原则
继承必须确保超类所拥有的性质在子类中仍然成立,即子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
(3)依赖倒置原则
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。
(4)单一职责原则
又称单一功能原则,这里的职责是指类变化的原因,单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
(5)接口隔离原则
要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。
(6)迪米特法则
如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
(7)合成复用原则
又叫组合/聚合复用原则,它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
2. 统一建模语言UML
此处主要介绍各种关系的表示方式,UML各种视图相关内容,请查阅 统一建模语言UML 相关文章内容。
在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)。
各种关系的强弱顺序: 泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖
3. 创建型模式
3.1 单例模式Singleton
(1)单例模式定义
单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
(2)实现方式
构造方法私有化,通过静态方法获取内部类生成的实例;
public class GracefullSingle {
private GracefullSingle(){ }
//类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
public static class SingleHolder{
静态初始化器,由JVM来保证线程安全
private static GracefullSingle gracefullSingle = new GracefullSingle();
}
public static GracefullSingle getGracefullSingleton(){
return SingleHolder.gracefullSingle;
}
}
(3)注意事项
懒汉单例模式:
懒汉式:顾名思义懒汉式就是应用刚启动的时候,并不创建实例,当外部调用该类的实例或者该类实例方法的时候,才创建该类的实例。是以时间换空间。
懒汉式的优点:实例在被使用的时候才被创建,可以节省系统资源,体现了延迟加载的思想。
延迟加载:通俗上将就是:一开始的时候不加载资源,一直等到马上就要使用这个资源的时候,躲不过去了才加载,这样可以尽可能的节省系统资源。
懒汉式的缺点:由于系统刚启动时且未被外部调用时,实例没有创建;如果一时间有多个线程同时调用LazySingleton.getLazyInstance()方法很有可能会产生多个实例。
也就是说下面的懒汉式在多线程下,是不能保持单例实例的唯一性的,要想保证多线程下的单例实例的唯一性得用同步,同步会导致多线程下由于争夺锁资源,运行效率不高。
饥汉式:顾名思义懒汉式就是应用刚启动的时候,不管外部有没有调用该类的实例方法,该类的实例就已经创建好了。以空间换时间。
饥汉式的优点:写法简单,在多线程下也能保证单例实例的唯一性,不用同步,运行效率高。
饥汉式的缺点:在外部没有使用到该类的时候,该类的实例就创建了,若该类实例的创建比较消耗系统资源,并且外部一直没有调用该实例,那么这部分的系统资源的消耗是没有意义的。
3.2 原型模式Prototype
(1)原型模式定义
原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
(2)实现方式
实现Cloneable接口,实现clone方法;
public class Prototype implements Cloneable {
public Prototype(){
System.out.println("this is construct method...");
}
@Override
protected Object clone() {
Prototype prototype = null;
try {
prototype = (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return prototype;
}
}
(3)注意事项
(1)使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。
不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。
单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
(2)深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。
如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
3.3 工厂方法模式FactoryMethod
工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式。简单工厂模式不在 GoF 23 种设计模式之列
(1)工厂方法模式定义
工厂方法模式是对简单工厂模式的进一步抽象化,将工厂进一步抽象化,使用具体的工厂类去生产不同的产品,引进新产品时只需增加新的工厂实现类和产品实现类即可,
其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
(2)实现方式
public interface LoggerFactory {
LoggerProduct createLogger();
}
public interface LoggerProduct {
void write();
}
public class FileLogger implements LoggerProduct {
public void write() {
System.out.println("file logger...");
}
}
public class DataBaseLogger implements LoggerProduct {
public void write() {
System.out.println("database logger...");
}
}
public class FileLoggerFactory implements LoggerFactory {
public LoggerProduct createLogger() {
return new FileLogger();
}
}
public class DataBaseLoggerFactory implements LoggerFactory {
public LoggerProduct createLogger() {
return new DataBaseLogger();
}
}
public class FactoryMethodMain {
public static void main(String[] args){
LoggerFactory loggerFactory = new DataBaseLoggerFactory();
loggerFactory.createLogger().write();
LoggerFactory loggerFactory1 = new FileLoggerFactory();
loggerFactory1.createLogger().write();
}
}
(3)注意事项
主要构成: 抽象工厂类、抽象产品类、具体工厂类、具体的产品类
结构:不同的具体工厂类生成不同的具体的产品类;扩展新产品类时,构建新的具体产品类和新的具体工厂类;
(4)结构图
3.4 抽象工厂模式Abstract Factory
(1)抽象工厂模式定义
抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
(2)实现方式
(1)两种产品,各有两种具体的产品实现类
public interface IEngine {
void create();
}
public interface ITire {
void create();
}
public class IEngin01Impl implements IEngine {
public void create() {
System.out.println("01 engine");
}
}
public class IEngine02Impl implements IEngine {
public void create() {
System.out.println("02 engine");
}
}
public class ITire01Impl implements ITire {
public void create() {
System.out.println("01 tire");
}
}
public class ITire02Impl implements ITire{
public void create() {
System.out.println("02 tire");
}
}
(2)抽象工厂,生产两种产品;不同的具体的工厂,生产不同的两种产品组合;
新的产品组合,需要创建新的对应具体工厂。
public abstract class CarAbstractFactory {
public abstract IEngine createEngine();
public abstract ITire createTire();
}
public class Car01Factory extends CarAbstractFactory{
public IEngine createEngine() {
return new IEngin01Impl();
}
public ITire createTire() {
return new ITire01Impl();
}
}
public class Car02Factory extends CarAbstractFactory {
public IEngine createEngine() {
return new IEngine02Impl();
}
public ITire createTire() {
return new ITire02Impl();
}
}
(3)应用
public class AbstractFactoryMain {
public static void main(String[] args){
CarAbstractFactory car01Factory = new Car01Factory();
car01Factory.createEngine().create();
car01Factory.createTire().create();
CarAbstractFactory car02Factory = new Car02Factory();
car02Factory.createEngine().create();
car02Factory.createTire().create();
}
}
(3)注意事项
构成:
(1)两种产品抽象类,各有多种具体的产品实现类
(2)抽象工厂类,可生产两种产品;不同的具体的工厂,生产不同的两种产品组合;
新的产品组合,需要创建新的对应具体工厂。
(4)结构图
3.5 建造者模式Builder
(1)建造者模式定义
建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。
它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
建造者模式,
是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
(2)实现方式
(1)产品类
public class Bike {
private IFrame iFrame;
private ITire iTire;
private IEngine iEngine;
public void setiFrame(IFrame iFrame) {
this.iFrame = iFrame;
}
public void setiTire(ITire iTire) {
this.iTire = iTire;
}
public void setiEngine(IEngine iEngine) {
this.iEngine = iEngine;
}
}
(2)抽象建造者
public interface BikeBuilder {
void buildFrame();
void buildTire();
void buildEngine();
Bike createBike();
}
(3)具体的建造者,不同的具体建造者,可以建造出不同结构于顺序的产品
public class MobaiBikeBuilder implements BikeBuilder {
Bike mbike = new Bike();
public void buildFrame() {
mbike.setiFrame(new IFrame());
}
public void buildTire() {
mbike.setiTire(new ITire());
}
public void buildEngine() {
mbike.setiEngine(new IEngine());
}
public Bike createBike() {
return mbike;
}
}
public class OfoBikeBuilder implements BikeBuilder{
Bike obike = new Bike();
public void buildFrame() {
obike.setiFrame(new IFrame());
}
public void buildTire() {
obike.setiTire(new ITire());
}
public void buildEngine() {
obike.setiEngine(new IEngine());
}
public Bike createBike() {
return obike;
}
}
(4)指挥者,依赖于抽象建造者,根据不同的具体建造者,创造出不同的产品;
public class BikeDirector {
private BikeBuilder bBuilder= null;
public BikeDirector(BikeBuilder bikeBuilder){
bBuilder = bikeBuilder;
}
public Bike conBike(){
bBuilder.buildFrame();
bBuilder.buildTire();
bBuilder.buildEngine();
return bBuilder.createBike();
}
}
(5)使用
public class BuilderMain {
public static void main(String[] args){
BikeDirector bikeDirector = new BikeDirector(new OfoBikeBuilder());
bikeDirector.conBike();
BikeDirector bikeDirector1 = new BikeDirector(new MobaiBikeBuilder());
bikeDirector1.conBike();
}
}
(3)注意事项
各角色的作用:
(1)指挥者(Director)直接和客户(Client)进行需求沟通;
(2)沟通后指挥者将客户创建产品的需求划分为各个部件的建造请求(Builder);
(3)将各个部件的建造请求委派到具体的建造者(ConcreteBuilder);
(4)各个具体建造者负责进行产品部件的构建;
(5)最终构建成具体产品(Product)。
(4)结构图
4. 结构型模式
结构性模式包含7中,分别为:代理模式、适配器模式、装饰模式、桥接模式、享元模式、门面模式、组合模式
4.1 代理模式Proxy
(1)定义
代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
根据代理的创建时期,代理模式分为静态代理和动态代理。
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
动态:在程序运行时,运用反射机制动态创建而成
(2)实现方式
(1)被代理接口类
public interface Subject {
void sayHello();
}
public class RealSubject implements Subject {
public void sayHello() {
System.out.println("hello,there!");
}
}
(2)代理类,实现InvocationHandler ,实现invoke方法;
public class ProxySubject implements InvocationHandler {
private Object object;
public ProxySubject(Object o){
this.object = o;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this.object, args);
}
}
(3)调用方
public class DynamicMain {
public static void main(String[] args){
Subject subject = new RealSubject();
ProxySubject ps = new ProxySubject(subject);
ClassLoader classLoader = subject.getClass().getClassLoader();
Subject subject1 = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, ps);
subject1.sayHello();
}
}
(3)注意事项
(1)代理类实现InvocationHandler类以及对应的invoke方法,并传入被代理对象对象接口;
(2)使用方 Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
参数:
(1)参数一:ClassLoader是指被代理对象实现接口的加载类;
(2)参数二:new Class[]是指class数组,是指被代理对象实现接口的class;
(3)参数三:InvocationHandler对象,即代理对象
4.2 适配器模式Adapter
(1)定义
适配器模式(Adapter)的定义:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
(2)实现方式
1)类适配器
i)目标接口
public interface Target {
void request();
}
ii)适配者类
public class Adaptee {
public void adapteeRequest(){
System.out.println("被适配类的方法...");
}
}
iii)适配器类
public class Adapter extends Adaptee implements Target{
public void request() {
super.adapteeRequest();
}
}
public class ClassAdapterMain {
public static void main(String[] args){
Target target = new Adapter();
target.request();
Adaptee adaptee = new Adapter();
adaptee.adapteeRequest();
}
}
2)对象适配器
i)目标接口
public interface IMobilePhone {
String google();
String apple();
}
ii)适配者类
public class HuaWei {
public String huawei(){
return "huawei:type-c";
}
}
iii)适配器类
public class Adapter implements IMobilePhone {
private HuaWei huaWei;
public Adapter(HuaWei huaWei){
this.huaWei = huaWei;
}
public String google() { return "google:type-c";}
public String apple() { return "apple:type-c"; }
public String huawei(){ return huaWei.huawei(); }
}
public class ObjectMain {
public static void main(String[] args){
HuaWei huaWei = new HuaWei();
Adapter adapter = new Adapter(huaWei);
System.out.println(adapter.apple());
System.out.println(adapter.google());
System.out.println(adapter.huawei());
}
}
(3)注意事项
适配器模式(Adapter)包含以下主要角色。
1)目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
2)适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
3)适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
适配器模式,使用接口方法去适配适配者功能;
类适配器模式: 适配器类继承适配者类的同时实现接口,在实现接口方法中调用适配者类的方法即可;
对象适配器模式:适配器类在实现接口的同时,聚合适配者对象作为成员变量,在实现接口方法中,调用适配者对象的方法。
4.3 桥接模式Bridge
(1)定义
桥接(Bridge)模式的定义:将抽象与实现分离,使它们可以独立变化。
它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
(2)实现方式
1)实现化
public interface Implementor {
void operation();
}
2)具体实现化
public class ConcreteImplementor01 implements Implementor{
public void operation() {
System.out.println("this is ConcreteImplementor01...");
}
}
public class ConcreteImplementor02 implements Implementor {
public void operation() {
System.out.println("this is ConcreteImplementor02...");
}
}
3)抽象化
public abstract class Abstration {
protect Implementor implementor;
public void setImplementor(Implementor implementor) {
this.implementor = implementor;
}
protected abstract void operation();
}
4)扩展抽象化
public class RefineAbstration extends Abstration {
public void operation() {
this.implementor.operation();
}
}
public class BridgeMain {
public static void main(String[] args){
Abstration abstration = new RefineAbstration();
Implementor implementor = new ConcreteImplementor01();
abstration.setImplementor(implementor);
abstration.operation();
Implementor implementor1 = new ConcreteImplementor02();
abstration.setImplementor(implementor1);
abstration.operation();
}
}
(3)注意事项
桥接(Bridge)模式包含以下主要角色。
1)抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
2)扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
3)实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
4)具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
4.4 装饰器模式Decorator
(1)定义
装饰器(Decorator)模式:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
(2)实现方式
1)抽象构件
public abstract class Component {
protected String name;
public String getName(){
return name;
}
public abstract void say();
}
2)具体构件
public class ConcreteComponentA extends Component{
public ConcreteComponentA(String name){
super.name = name;
}
public void say() {
System.out.print(".CA.");
}
}
public class ConcreteComponentB extends Component {
public ConcreteComponentB(String name){
super.name = name;
}
public void say() {
System.out.print(".CB.");
}
}
3)抽象装饰,集成抽象构件,并聚合抽象构件为成员变量
public abstract class Decorator extends Component {
protected Component component;
public void say(){};
}
4)具体装饰
public class ConcreteDecorateA extends Decorator {
public ConcreteDecorateA(Component component){
super.component = component;
}
@Override
public void say() {
component.say();
System.out.print(".DA.");
}
}
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component){
super.component = component;
}
@Override
public void say() {
component.say();
System.out.print(".DB.");
}
}
5)客户端使用
public class TestMain {
public static void main(String[] args){
Decorator decorator = new ConcreteDecorateA(new ConcreteComponentA("ca"));
decorator.say();
System.out.println("###########################");
Decorator decorator1 = new ConcreteDecoratorB(new ConcreteComponentA("ca"));
decorator1.say();
System.out.println("##########################");
Decorator decorator2 = new ConcreteDecoratorB(new ConcreteDecoratorB(new ConcreteComponentB("cb")));
decorator2.say();
}
}
(3)注意事项
装饰器模式主要包含以下角色。
1)抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
2)具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
3)抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
4)具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
4.5 外观模式Facade
(1)定义
外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。
该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
(2)实现方式
public class RepairLight {
public void repair(){
System.out.println("修点灯...");
}
}
public class RepairWater {
public void repair(){
System.out.println("修水龙头");
}
}
public class Facade {
private RepairLight repairLight = new RepairLight();
private RepairWater repairWater = new RepairWater();
public void repairLight(){
repairLight.repair();
}
public void repairWater(){
repairWater.repair();
}
public void repairLightAndWater(){
repairWater.repair();
repairLight.repair();
}
}
public class FacadeMain {
public static void main(String[] args){
Facade facade = new Facade();
facade.repairLightAndWater();
}
}
(3)注意事项
外观类聚合子系统类,并集成调用子系统类的相关方法;
通过外观类,实现调用多个子系统的作用
4.6 享元模式Flyweight
(1)定义
享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
享元模式的主要优点是:相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
(2)实现方式
1)享元抽象类
public abstract class IgoChessman {
public abstract String chessColor();
public void display(){
System.out.println("棋子颜色:"+this.chessColor());
}
}
2)享元抽象具体实现类
public class WhiteIgoChessman extends IgoChessman {
public String chessColor() {
return "白色";
}
}
public class BlackIgoChessman extends IgoChessman {
public String chessColor() {
return "黑色";
}
}
3)享元工厂类
public class IgoChessmanFactory {
private static IgoChessmanFactory igoChessmanFactory = new IgoChessmanFactory();
private static Map<String,IgoChessman> ht ;
private IgoChessmanFactory(){
ht = new HashMap<String, IgoChessman>();
IgoChessman whiteIgoChessman = new WhiteIgoChessman();
IgoChessman blackIgoChessman = new BlackIgoChessman();
ht.put("白色", whiteIgoChessman);
ht.put("黑色", blackIgoChessman);
}
public static IgoChessmanFactory getIgoChessmanFactory() {
return igoChessmanFactory;
}
public static IgoChessman getIgoChessman(String name){
return ht.get(name);
}
}
4)客户端使用
public class IgoFlyMain {
public static void main(String[] args){
IgoChessman w1 = IgoChessmanFactory.getIgoChessman("白色");
IgoChessman w2 = IgoChessmanFactory.getIgoChessman("白色");
System.out.println(w1==w2);
IgoChessman b1 = IgoChessmanFactory.getIgoChessman("黑色");
IgoChessman b2 = IgoChessmanFactory.getIgoChessman("黑色");
System.out.println(b1==b2);
w1.display();
w2.display();
}
}
(3)注意事项
享元模式的主要角色有如下。
1)抽象享元(Flyweight)类:是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
2)具体享元(Concrete Flyweight)类:实现抽象享元角色中所规定的接口。
3)非享元(Unsharable Flyweight)类:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
4)享元工厂(Flyweight Factory)类:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
4.7 组合模式Composite
(1)定义
组合(Composite Pattern)模式:又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,
使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。
(2)实现方式
1)抽象构件
public abstract class Component {
private String name;
public Component(String name){
this.name = name;
}
public void getName(){
System.out.println(this.name);
}
}
2)树枝构件
public class Composite extends Component {
private LinkedList<Component> childs;
public Composite(String name) {
super(name);
this.childs = new LinkedList<Component>();
}
public void add(Component child){
this.childs.add(child);
}
public void remove(String child){
this.childs.remove(child);
}
public LinkedList<Component> getChilds(){
return this.childs;
}
}
3)树叶构件
public class Leaf extends Component {
public Leaf(String name) {
super(name);
}
}
4)客户端使用
public class SaftyMain {
public static void main(String[] args){
Composite composite = new Composite("root");
Composite composite1 = new Composite("child01");
Composite composite2 = new Composite("child02");
Composite composite11 = new Composite("child011");
Leaf leaf = new Leaf("leaf01");
Leaf leaf1 = new Leaf("leaf011");
composite.add(composite1);
composite.add(composite2);
composite.add(leaf);
composite2.add(composite11);
composite2.add(leaf1);
displayTree(composite);
}
public static void displayTree(Composite composite){
LinkedList<Component> components = composite.getChilds();
for(Component component: components){
if(component instanceof Leaf){
component.getName();
}else {
component.getName();
displayTree((Composite) component);
}
}
}
}
(3)注意事项
实现要点:
1)树枝和树叶都实现抽象构件,树枝聚合抽象构件列表;
2)通过树枝的抽象构件列表,可以进一步增加树枝与树叶,从而形成树状结构;
组合模式中的透明式和安全式:
1)安全式:上文实现方式中是安全式,即在树枝中聚合抽象构件列表,在树枝中拥有对聚合构件列表的增删改操作等;
2)透明式:透明式,是在抽象构件中聚合其自身列表,同时拥有增删改等操作;而在树枝中,对相关方法进行实现;而树叶不支持增删改操作,需要抛出相关异常;
5. 行为型模式
行为型模式有11中,分别为:模板方法模式、策略模式、命令模式、责任链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式、解释器模式
5.1 模板方法模式Template Method
(1)定义
模板方法(Template Method)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,
使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
(2)实现方式
1)抽象类/抽象模板
public abstract class TemplateAbstract {
//模板方法
public void TemplateMethod() {
SpecificMethod();
abstractMethod1();
abstractMethod2();
}
//具体方法
public void SpecificMethod() {
System.out.println("抽象类中的具体方法被调用...");
}
public abstract void abstractMethod1(); //抽象方法1
public abstract void abstractMethod2(); //抽象方法2
}
2)具体子类/具体实现
public class TemplateConcrete extends TemplateAbstract {
public void abstractMethod1() {
System.out.println("抽象方法1的实现被调用...");
}
public void abstractMethod2() {
System.out.println("抽象方法2的实现被调用...");
}
}
public class Demo01Client {
public static void main(String[] args){
TemplateAbstract tm=new TemplateConcrete();
tm.TemplateMethod();
}
}
(3)注意事项
1)抽象模板类,负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下。
(a)模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
(b)基本方法:是整个算法中的一个步骤,包含以下几种类型。
抽象方法:在抽象类中声明,由具体子类实现。
具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
2)具体子类/具体实现(Concrete Class)
具体实现类,实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
5.2 策略模式Strategy
(1)定义
策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
(2)实现方式
public interface IStrategy {
//定义的抽象算法方法 来约束具体的算法实现方法
public void algorithmMethod();
}
public class ConcreteStrategy01 implements IStrategy {
@Override
public void algorithmMethod() {
System.out.println("this is ConcreteStrategy01 method...");
}
}
public class ConcreteStrategy02 implements IStrategy {
@Override
public void algorithmMethod() {
System.out.println("this is ConcreteStrategy02 method...");
}
}
public class ContextStrategy {
//持有一个策略实现的引用
private IStrategy strategy;
//使用构造器注入具体的策略类
public ContextStrategy(IStrategy strategy) {
this.strategy = strategy;
}
public void contextMethod(){
//调用策略实现的方法
strategy.algorithmMethod();
}
}
public class Demo01Client {
public static void main(String[] args){
//1.创建具体测策略实现
IStrategy strategy = new ConcreteStrategy01();
//2.在创建策略上下文的同时,将具体的策略实现对象注入到策略上下文当中
ContextStrategy contextStrategy = new ContextStrategy(strategy);
//3.调用上下文对象的方法来完成对具体策略实现的回调
contextStrategy.contextMethod();
}
}
(3)注意事项
策略模式的主要角色如下。
1)抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
2)具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
3)环境(Context)类:持有一个策略类的引用,最终给客户端调用。
(4)类图结构
5.3 命令模式Command
(1)定义
命令(Command)模式的定义如下:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
(2)实现方式
1)抽象命令类
public abstract class Command {
public abstract void execute();
}
2)具体命令类
public class ConcreteCommand01 extends Command {
public Receiver receiver;
public ConcreteCommand01(Receiver receiver){
this.receiver = receiver;
}
public void execute() {
this.receiver.doSomething();
}
}
3)抽象接收者
public abstract class Receiver {
public abstract void doSomething();
}
4)具体接收者
public class ConcreteReceiver01 extends Receiver {
public void doSomething() {
System.out.println("this is concreteReceiver01.......");
}
}
5)调用者
public class Invoker {
private Command command;
public Invoker(Command command){
this.command = command;
}
public void action(){
this.command.execute();
}
}
public class ClientMain {
public static void main(String[] args){
Receiver receiver = new ConcreteReceiver01();
Command command = new ConcreteCommand01(receiver);
Invoker invoker = new Invoker(command);
invoker.action();
}
}
(3)注意事项
命令模式包含以下主要角色。
1)抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
2)具体命令类(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
3)实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
4)调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
5.4 责任链模式Chain of Responsibility
(1)定义
责任链(Chain of Responsibility)模式:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;
当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
(2)实现方式
1)抽象处理者
public abstract class Handler {
private Handler next;
public void setNext(Handler next) {
this.next=next;
}
public Handler getNext() {
return next;
}
public abstract void handleRequest(String request);
}
2)具体处理者
public class ConcreteHandler01 extends Handler {
public void handleRequest(String request) {
if(request.equals("one")) {
System.out.println("具体处理者1负责处理该请求!");
} else {
if(getNext()!=null) {
getNext().handleRequest(request);
} else {
System.out.println("没有人处理该请求!");
}
}
}
}
public class ConcreteHandler02 extends Handler {
public void handleRequest(String request) {
if(request.equals("two")) {
System.out.println("具体处理者2负责处理该请求!");
} else {
if(getNext()!=null) {
getNext().handleRequest(request);
} else {
System.out.println("没有人处理该请求!");
}
}
}
}
public class ChainOfResponsibilityPatternMain {
public static void main(String[] args){
//组装责任链
Handler handler1=new ConcreteHandler01();
Handler handler2=new ConcreteHandler02();
handler1.setNext(handler2);
//提交请求
handler1.handleRequest("two");
}
}
(3)注意事项
职责链模式主要包含以下角色:
1)抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
2)具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
3)客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
实现方式,抽象处理者中聚合其自身作为成员变量,并可将该成员变量作为当前对象的下一个链节点,具体处理者处理请求,并根据条件判断是让当前对象处理还是交给下一个节点进行处理,从而形成链式结构。
5.5 状态模式State
(1)定义
状态(State)模式:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
(2)实现方式
1)抽象状态
public interface State {
// 状态对应的处理
public void handle(String sampleParameter);
}
2)具体状态A
public class ConcreteStateA implements State {
@Override
public void handle(String sampleParameter) {
System.out.println("ConcreteStateA handle :" + sampleParameter);
}
}
3)具体状态B
public class ConcreteStateB implements State {
@Override
public void handle(String sampleParameter) {
System.out.println("ConcreteStateB handle :" + sampleParameter);
}
}
4)环境类角色,聚合状态类作为成员变量,并在执行方法中调用状态类的方法
public class Context {
// 持有一个State类型的对象实例
private State state;
public void setState(State state) {
this.state = state;
}
// 用户感兴趣的接口方法
public void request(String param) {
// 转调state来处理
state.handle(param);
}
}
public class StateDemo01Client {
public static void main(String[] args){
// 创建状态
State state = new ConcreteStateA();
Context context = new Context();
context.setState(state);
// 请求
context.request("test");
State state1 = new ConcreteStateB();
context.setState(state1);
context.request("test");
}
}
(3)注意事项
状态模式包含以下主要角色。
1)环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
2)抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
3)具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
5.6 观察者模式Observer
(1)定义
观察者(Observer)模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
这种模式有时又称作发布-订阅模式、模型-视图模式。
(2)实现方式
1)抽象观察者
interface Observer{
void response(); //反应
}
2)具体观察者
class ConcreteObserver01 implements Observer{
public void response(){
System.out.println("具体观察者1作出反应!");
}
}
class ConcreteObserver02 implements Observer {
public void response() {
System.out.println("具体观察者2作出反应!");
}
}
3)抽象主题
abstract class Subject {
protected List<Observer> observers=new ArrayList<Observer>();
//增加观察者方法
public void add(Observer observer) {
observers.add(observer);
}
//删除观察者方法
public void remove(Observer observer){
observers.remove(observer);
}
public abstract void notifyObserver(); //通知观察者方法
}
4)具体主题
class ConcreteSubject extends Subject {
public void notifyObserver() {
System.out.println("具体目标发生改变...");
System.out.println("--------------");
for(Object obs:observers) {
((Observer)obs).response();
}
}
}
public class Demo01TestMain {
public static void main(String[] args) {
Subject subject=new ConcreteSubject();
Observer obs1=new ConcreteObserver01();
Observer obs2=new ConcreteObserver02();
subject.add(obs1);
subject.add(obs2);
subject.notifyObserver();
}
}
(3)注意事项
1)抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
2)具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
3)抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
4)具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
5.7 中介者模式Mediator
(1)定义
中介者(Mediator)模式:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。
中介者模式又叫调停模式,它是迪米特法则的典型应用。
(2)实现方式
public abstract class Colleague {
protected Mediator mediator;
public void setMedium(Mediator mediator) {
this.mediator=mediator;
}
public abstract void receive();
public abstract void send();
}
public class ConcreteColleague01 extends Colleague {
public void receive() {
System.out.println("具体同事类01收到请求。");
}
public void send() {
System.out.println("具体同事类01发出请求。");
mediator.relay(this);
}
}
public abstract class Mediator {
public abstract void register(Colleague colleague);
public abstract void relay(Colleague cl); //转发
}
public class ConcreteMediator extends Mediator {
private List<Colleague> colleagues=new ArrayList<Colleague>();
public void register(Colleague colleague) {
if(!colleagues.contains(colleague)){
colleagues.add(colleague);
colleague.setMedium(this);
}
}
public void relay(Colleague cl) {
for(Colleague ob:colleagues){
if(!ob.equals(cl)){
ob.receive();
}
}
}
}
public class Mediator01Main {
public static void main(String[] args){
Colleague c1 = new ConcreteColleague01();
Colleague c2 = new ConcreteColleague02();
Mediator mediator = new ConcreteMediator();
mediator.register(c1);
mediator.register(c2);
c1.send();
}
}
(3)注意事项
中介者模式包含以下主要角色。
1)抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
2)具体中介者(Concrete Mediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
3)抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
4)具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
5.8 迭代器模式Iterator
(1)定义
迭代器(Iterator)模式:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
(2)实现方式
public interface Iterator {
public void first();
public void next();
public boolean isDone();
public Object currentItem();
}
public class ConcreteIterator implements Iterator {
private ConcreteAggregate agg;
private int index = 0;
private int size = 0;
public ConcreteIterator(ConcreteAggregate agg){
this.agg = agg;
this.size = agg.size();
index = 0;
}
public Object currentItem() {
return agg.getElement(index);
}
public void first() {
index = 0;
}
public boolean isDone() {
return (index >= size);
}
public void next() {
if(index < size) {
index ++;
}
}
}
public abstract class Aggregate {
public abstract Iterator createIterator();
}
public class ConcreteAggregate extends Aggregate {
private Object[] objArray = null;
public ConcreteAggregate(Object[] objArray){
this.objArray = objArray;
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
public Object getElement(int index){
if(index < objArray.length){
return objArray[index];
}else{
return null;
}
}
public int size(){
return objArray.length;
}
}
public class IteratorMain {
public static void main(String[] args){
Object[] objArray = {"One","Two","Three","Four","Five","Six"};
Aggregate agg = new ConcreteAggregate(objArray);
Iterator it = agg.createIterator();
while(!it.isDone()){
System.out.println(it.currentItem());
it.next();
}
}
}
(3)注意事项
迭代器模式主要包含以下角色:
(1)抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
(2)具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
(3)抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
(4)具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
5.9 访问者模式Visitor
(1)定义
访问者(Visitor)模式:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,
为数据结构中的每个元素提供多种访问方式。
(2)实现方式
interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
public class ConcreteVisitorA implements Visitor {
public void visit(ConcreteElementA element) {
System.out.println("具体访问者A访问-->"+element.operationA());
}
public void visit(ConcreteElementB element){
System.out.println("具体访问者A访问-->"+element.operationB());
}
}
public class ConcreteVisitorB implements Visitor{
public void visit(ConcreteElementA element){
System.out.println("具体访问者B访问-->"+element.operationA());
}
public void visit(ConcreteElementB element) {
System.out.println("具体访问者B访问-->"+element.operationB());
}
}
public interface Element {
void accept(Visitor visitor);
}
public class ConcreteElementA implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationA() {
return "具体元素A的操作。";
}
}
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationB() {
return "具体元素B的操作。";
}
}
public class ObjectStructure {
private List<Element> list=new ArrayList<Element>();
public void accept(Visitor visitor) {
Iterator<Element> i=list.iterator();
while(i.hasNext()) {
((Element) i.next()).accept(visitor);
}
}
public void add(Element element) {
list.add(element);
}
public void remove(Element element) {
list.remove(element);
}
}
public class Demo01Client {
public static void main(String[] args) {
ObjectStructure os=new ObjectStructure();
os.add(new ConcreteElementA());
os.add(new ConcreteElementB());
Visitor visitor=new ConcreteVisitorA();
os.accept(visitor);
System.out.println("------------------------");
visitor=new ConcreteVisitorB();
os.accept(visitor);
}
}
(3)注意事项
访问者模式包含以下主要角色:
(1)抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
(2)具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
(3)抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
(4)具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
(5)对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
5.10 备忘录模式Memento
(1)定义
备忘录(Memento)模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,
以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
(2)实现方式
public class Memento {
private String state;
public Memento(String state) {
this.state=state;
}
public void setState(String state) {
this.state=state;
}
public String getState() {
return state;
}
}
class Originator {
private String state;
public void setState(String state) {
this.state=state;
}
public String getState() {
return state;
}
public Memento createMemento() {
return new Memento(state);
}
public void restoreMemento(Memento m) {
this.setState(m.getState());
}
}
class Caretaker {
private Memento memento;
public void setMemento(Memento m) {
memento=m;
}
public Memento getMemento() {
return memento;
}
}
public class MementoClient01Main {
public static void main(String[] args) {
Originator or=new Originator();
Caretaker cr=new Caretaker();
or.setState("S0");
System.out.println("初始状态:"+or.getState());
cr.setMemento(or.createMemento()); //保存状态
or.setState("S1");
System.out.println("新的状态:"+or.getState());
or.restoreMemento(cr.getMemento()); //恢复状态
System.out.println("恢复状态:"+or.getState());
}
}
(3)注意事项
备忘录模式的主要角色如下:
(1)发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
(2)备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
(3)管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
5.11 解释器模式Interpreter
(1)定义
解释器(Interpreter)模式:给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。
用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。
(2)实现方式
public abstract class Expression {
abstract int interpreter(Context context);
}
public class TerminalExpression extends Expression {
String variable;
public TerminalExpression(String variable){
this.variable = variable;
}
int interpreter(Context context) {
return context.lookup(this);
}
}
public abstract class NoTerminalExpression extends Expression {
Expression e1,e2;
public NoTerminalExpression(Expression e1,Expression e2){
this.e1 = e1;
this.e2 = e2;
}
}
public class MinusOperation extends NoTerminalExpression {
public MinusOperation(Expression e1,Expression e2){
super(e1,e2);
}
int interpreter(Context context) {
return this.e1.interpreter(context)-this.e2.interpreter(context);
}
}
public class PlusOperation extends NoTerminalExpression {
public PlusOperation(Expression e1,Expression e2){
super(e1,e2);
}
int interpreter(Context context) {
return this.e1.interpreter(context)+this.e2.interpreter(context);
}
}
public class Context {
private Map<Expression,Integer> map = new HashMap<Expression,Integer>();
public void add(Expression e, Integer value){
map.put(e, value);
}
public int lookup(Expression expression){
return map.get(expression);
}
}
public class ExpressionMain {
public static void main(String[] args){
Context context = new Context();
TerminalExpression a = new TerminalExpression("a");
TerminalExpression b = new TerminalExpression("b");
context.add(a, 10);
context.add(b, 20);
System.out.println(a.interpreter(context));
System.out.println(new PlusOperation(a, b).interpreter(context));
System.out.println(new MinusOperation(a, b).interpreter(context));
}
}
(3)注意事项
解释器模式包含以下主要角色。
(1)抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
(2)终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
(3)非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
(4)环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
(5)客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。
6. 代码示例
链接: https://github.com/shy871/design-pattern.
7. 参考资料
[1] http://c.biancheng.net/view/1317.html
[2] https://www.runoob.com/design-pattern/design-pattern-tutorial.html
[3] https://www.cnblogs.com/guohai-stronger/p/11883743.html