java设计模式
2020-11-04 14:30:53 4 举报
AI智能生成
java设计模式
作者其他创作
大纲/内容
开闭原则
定义
软件实体应当对扩展开放,对修改关闭。
作用
1. 保持软件产品的稳定性:开闭原则要求我们通过保持原有代码不变,添加新代码来实现软件的变化,不涉及原代码的改动。
2. 使代码更具模块化,易于维护:开闭原则让模块间代码独立不相互调用,更改一个功能的代码也不会引起其他功能的崩溃。
3. 提高开发效率:不需要看懂原有代码实现细节便可以添加新代码实现新功能。
2. 使代码更具模块化,易于维护:开闭原则让模块间代码独立不相互调用,更改一个功能的代码也不会引起其他功能的崩溃。
3. 提高开发效率:不需要看懂原有代码实现细节便可以添加新代码实现新功能。
实例参考
在原有的代码中进行修改,其风险远比扩展和实现一个方法要大的多。
里氏替换原则
定义
所有引用基类(父类)的地方必须能透明地使用其子类的对象:通俗讲就是,使用基类对象的地方能完全替换成子类,同时代码及其业务逻辑不会出错。
作用
1. 是实现开闭原则重要方式之一,加强程序的健壮性,同时版本升级也可以做到非常好的兼容性
2. 增加子类,原有的子类还可以继续运行
3. 每个子类对应了不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑
2. 增加子类,原有的子类还可以继续运行
3. 每个子类对应了不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑
规则
1. 子类可以实现父类的抽象方法,但尽量不要覆盖父类的非抽象方法: 如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏;子类中可以增加自己特有的方法;
2. 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松;
3. 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的的输出/返回值)要比父类的方法更严格或相等;
2. 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松;
3. 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的的输出/返回值)要比父类的方法更严格或相等;
依赖倒置原则
定义
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。
作用
- 降低类间的耦合性。
- 提高系统的稳定性。
- 减少并行开发引起的风险。
- 提高代码的可读性和可维护性。
规则
- 每个类尽量提供接口或抽象类,或者两者都具备。
- 变量的声明类型尽量是接口或者是抽象类。
- 任何类都不应该从具体类派生。
- 使用继承时尽量遵循里氏替换原则。
单一职责原则
定义
这里的职责是指类变化的原因,单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
作用
控制类的粒度大小、将对象解耦、提高其内聚性。
接口隔离原则
定义
要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
作用
约束接口、降低类对接口的依赖性
与单一职责原则区别
1. 单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。
2. 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。
2. 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。
迪米特法则
定义
只与你的直接朋友交谈,不跟“陌生人”说话;如果两个类不必彼此直接通信,那么这两个类就不应当直接的相互作用,如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
作用
1. 限制软件实体之间通信的宽度和尝试。降低了类之间的耦合度,提高了模块的相对独立性。
2. 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。
2. 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。
规则
1. 从依赖者的角度来说,只依赖应该依赖的对象。
2. 从被依赖者的角度说,只暴露应该暴露的方法。
2. 从被依赖者的角度说,只暴露应该暴露的方法。
合成复用原则
定义
在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
作用
通常类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优点,但它也存在以下缺点。
继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。
采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点。
它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。
复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。
继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。
采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点。
它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。
复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。
规则
合成复用原则是通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。
创建型
Singleton(单例)
定义:确保一个类只有一个实例,并提供全局访问点
要点
1、单件模式确保程序中一个类最多只有一个实例
2、单件模式也提供访问这个实例的全局点
3、实现单件模式需要么有的构造器、一个静态方法、一个静态变量
4、确定在性能和资源上的限制,然后小心地选择适当的方案来实现单件,以解决多线程问题(我们必须认定所有的程序都是多线程的)
5、小心,如果使用多个类加载器,可能导致单件失效而产生多个实例
要点
1、单件模式确保程序中一个类最多只有一个实例
2、单件模式也提供访问这个实例的全局点
3、实现单件模式需要么有的构造器、一个静态方法、一个静态变量
4、确定在性能和资源上的限制,然后小心地选择适当的方案来实现单件,以解决多线程问题(我们必须认定所有的程序都是多线程的)
5、小心,如果使用多个类加载器,可能导致单件失效而产生多个实例
Prototype(原型)
定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
优点:
Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点:
需要为每一个类都配置一个 clone 方法
clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
优点:
Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点:
需要为每一个类都配置一个 clone 方法
clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
FactoryMethod(工厂方法)
定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
1、所有的工厂都是用来封装对象的创建
2、简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦
3、工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象
4、所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合
5、工厂方法允许类将实例化延迟到子类进行
6、依赖倒置原则,指导我们避免依赖具体类型,而要依赖抽象
7、工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程
1、所有的工厂都是用来封装对象的创建
2、简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦
3、工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象
4、所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合
5、工厂方法允许类将实例化延迟到子类进行
6、依赖倒置原则,指导我们避免依赖具体类型,而要依赖抽象
7、工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程
AbstractFactory(抽象工厂)
定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
1、抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中
2、抽象工厂创建相关的对象家族,而不需要依赖它们的具体类
1、抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中
2、抽象工厂创建相关的对象家族,而不需要依赖它们的具体类
Builder(建造者)
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成。
主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
如何使用:用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)
解决的问题:方便用户创建复杂的对象(不需要知道实现过程);代码复用性 & 封装性(将对象构建过程和细节进行封装 & 复用)
与工厂模式的区别是:建造者模式更加关注与零件装配的顺序,一般用来创建更为复杂的对象。工厂方法模式更注重零部件的创建过程,但两者可以结合使用
主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
如何使用:用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)
解决的问题:方便用户创建复杂的对象(不需要知道实现过程);代码复用性 & 封装性(将对象构建过程和细节进行封装 & 复用)
与工厂模式的区别是:建造者模式更加关注与零件装配的顺序,一般用来创建更为复杂的对象。工厂方法模式更注重零部件的创建过程,但两者可以结合使用
结构型
Proxy(代理)
定义:为另一个对象提供一个替身或占位符以访问这个对象。
要点
1、代理模式为另一个对象提供代表,以便控制客户对对象的访问,管理访问的方式有许多种
2、远程代理管理客户和远程对象之间的交互
3、虚拟代理控制访问实例化开销大的对象
4、保护代理基于调用者控制对对象方法的访问
5、代理模式有许多变体,例如:缓存代理、同步代理、防火墙代理和写入时复制代理
6、代理在结构上类似装饰者,但是目的不同
7、装饰者模式为对象加上行为,而代理则是控制访问
8、java内置的代理支持,可以根据需要建立动态代理,并将所有调用分配到所选的处理器
9、就和其他的包装者(wrapper)一样,代理会造成你的设计中类的数目增加
要点
1、代理模式为另一个对象提供代表,以便控制客户对对象的访问,管理访问的方式有许多种
2、远程代理管理客户和远程对象之间的交互
3、虚拟代理控制访问实例化开销大的对象
4、保护代理基于调用者控制对对象方法的访问
5、代理模式有许多变体,例如:缓存代理、同步代理、防火墙代理和写入时复制代理
6、代理在结构上类似装饰者,但是目的不同
7、装饰者模式为对象加上行为,而代理则是控制访问
8、java内置的代理支持,可以根据需要建立动态代理,并将所有调用分配到所选的处理器
9、就和其他的包装者(wrapper)一样,代理会造成你的设计中类的数目增加
静态代理
代理和被代理对象在代理之前是确定的,他们都实现相同的接口或者继承相同的抽象类
动态代理
代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
CGLIB动态代理
1、需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
2、引入功能包后,就可以在内存中动态构建子类
3、代理的类不能为final,否则报错
4、目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
2、引入功能包后,就可以在内存中动态构建子类
3、代理的类不能为final,否则报错
4、目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
Adapter(适配器)
定义:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
要点
1、当需要使用一个现有的类而其接口并不符合你的需要时,就使用适配器
2、适配器有两种形式:对象适配器和类适配器。类适配器需要用到多重继承
3、适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;而外观将一群对象“包装”起来以简化其接口
要点
1、当需要使用一个现有的类而其接口并不符合你的需要时,就使用适配器
2、适配器有两种形式:对象适配器和类适配器。类适配器需要用到多重继承
3、适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;而外观将一群对象“包装”起来以简化其接口
Bridge(桥接)
定义:桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
模式的结构:
模式的结构:
- 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
Decorator(装饰者)
定义:动态地将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一个选择。
要点:
1、继承属于扩展形式之一,但不见得是达到弹性设计的最佳方式
2、在我们的设计中,应该允许行为可以被扩展,而无须修改现有的代码
3、组合和委托可用于在运行时动态地加上新的行为
4、除了继承,装饰者模式也可以让我们扩展行为
5、装饰者模式意为者一群装饰者类,这些类用来包装具体的组件
6、装饰者类反映出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现)
7、装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的
8、你可以用无数个装饰者包装一个组件
9、装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型
10、装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂
模式的结构:
要点:
1、继承属于扩展形式之一,但不见得是达到弹性设计的最佳方式
2、在我们的设计中,应该允许行为可以被扩展,而无须修改现有的代码
3、组合和委托可用于在运行时动态地加上新的行为
4、除了继承,装饰者模式也可以让我们扩展行为
5、装饰者模式意为者一群装饰者类,这些类用来包装具体的组件
6、装饰者类反映出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现)
7、装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的
8、你可以用无数个装饰者包装一个组件
9、装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型
10、装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂
模式的结构:
- 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
Facade(外观)
定义:提供一个高层接口,抽象了一系列接口的功能,使用者只关注外观,无需关注具体设备实现。
模式的结构:
模式的结构:
- 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
- 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
- 客户(Client)角色:通过一个外观角色访问各个子系统的功能。
Flyweight(享元)
定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
模式的结构:
模式的结构:
- 抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
- 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
- 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
- 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
Composite(组合)
定义:部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。
模式的结构:
模式的结构:
- 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
- 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
- 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
行为型
Template Method(模版方法)
定义:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
要点:
1、模板方法定义了算法的步骤,把这些步骤的实现延迟到子类
2、模板方法模式为我们提供了一种代码复用的重要技巧
3、模板方法的抽象类可以定义具体方法、抽象方法和钩子
4、抽象方法由子类实现
5、钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它
6、为了防止子类改变模板方法中的算法,可以将模板方法声明为final
7、好莱坞原则告诉我们,将决策权放在高层模块中,以便决定如何以及何时调用低层模块
8、你将在真实世界代码中看到模板方法模式的许多变体,不要期待它们全过都是一眼就可以被你认出的
9、策略模式和模板方法模式都封装算法,一个用组合,一个用继承
10、工厂方法是模板方法的一版特殊版本
要点:
1、模板方法定义了算法的步骤,把这些步骤的实现延迟到子类
2、模板方法模式为我们提供了一种代码复用的重要技巧
3、模板方法的抽象类可以定义具体方法、抽象方法和钩子
4、抽象方法由子类实现
5、钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它
6、为了防止子类改变模板方法中的算法,可以将模板方法声明为final
7、好莱坞原则告诉我们,将决策权放在高层模块中,以便决定如何以及何时调用低层模块
8、你将在真实世界代码中看到模板方法模式的许多变体,不要期待它们全过都是一眼就可以被你认出的
9、策略模式和模板方法模式都封装算法,一个用组合,一个用继承
10、工厂方法是模板方法的一版特殊版本
Strategy(策略)
定义:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
要点:
1、知道OO基础,并不足以让你设计良好的OO系统
2、良好的OO设计必须具备可复用、可扩充、可维护三个特性
3、模式可以让我们建造出具有良好OO设计质量的系统
4、模式被认为是历经验证的OO设计经验
5、模式不是代码,而是针对设计问题的能用解决方案。你可把它们应用到特定的应用中
6、模式不是被发明,而是被发现
7、大多数的模式和原则,都着眼于软件变化的主题
8、大多数的模式都允许系统局部改变独立于其他部分
9、我们常把系统中会变化的部分抽出来封装
10、模式让开发人员之间有共享的语言,能够最大化沟通的价值
要点:
1、知道OO基础,并不足以让你设计良好的OO系统
2、良好的OO设计必须具备可复用、可扩充、可维护三个特性
3、模式可以让我们建造出具有良好OO设计质量的系统
4、模式被认为是历经验证的OO设计经验
5、模式不是代码,而是针对设计问题的能用解决方案。你可把它们应用到特定的应用中
6、模式不是被发明,而是被发现
7、大多数的模式和原则,都着眼于软件变化的主题
8、大多数的模式都允许系统局部改变独立于其他部分
9、我们常把系统中会变化的部分抽出来封装
10、模式让开发人员之间有共享的语言,能够最大化沟通的价值
command(命令)
定义:将请求封装成对象,这可以让你使用不同的请求、队列,或者日志请求来参数化其他对象。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。命令模式也是可以支持撤销操作。
要点:
1、命令模式将发出请求的对象和执行请求的对象解耦
2、在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作
3、调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用
4、调用者可以接受命令当做参数,甚至在运行时动态的进行
5、命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态
6、宏命令是命令的一种简单的延伸,允许调用多个命令。宏方法也可以支持撤销
7、实际操作时,很常见使用“聪明”命令对象,也就是直接实现了请求,而不是将工作委托给接收者
8、命令也可以用来实现日志和事务系统
要点:
1、命令模式将发出请求的对象和执行请求的对象解耦
2、在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作
3、调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用
4、调用者可以接受命令当做参数,甚至在运行时动态的进行
5、命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态
6、宏命令是命令的一种简单的延伸,允许调用多个命令。宏方法也可以支持撤销
7、实际操作时,很常见使用“聪明”命令对象,也就是直接实现了请求,而不是将工作委托给接收者
8、命令也可以用来实现日志和事务系统
Chain Of Responsibility(责任链)
定义:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
State(状态)
定义:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
要点:
1、状态模式允许一个对象基于内部状态而拥有不同的行为
2、和程序状态机(PSM)不同,状态模式用类代表状态
3、Context会将行为委托给当前状态对象
4、通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了
5、状态模式和策略模式有相同的类图,但是它们的意图不同
6、策略模式通常会用行为或算法来配置Context类
7、状态模式允许Context随着状态的改变而改变行为
8、状态转换可以由State类或Context类控制
9、使用状态模式通常会导致设计中类的数目大量增加
10、状态类可以被多个Context实例共享
要点:
1、状态模式允许一个对象基于内部状态而拥有不同的行为
2、和程序状态机(PSM)不同,状态模式用类代表状态
3、Context会将行为委托给当前状态对象
4、通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了
5、状态模式和策略模式有相同的类图,但是它们的意图不同
6、策略模式通常会用行为或算法来配置Context类
7、状态模式允许Context随着状态的改变而改变行为
8、状态转换可以由State类或Context类控制
9、使用状态模式通常会导致设计中类的数目大量增加
10、状态类可以被多个Context实例共享
Observer(观察者)
定义:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
要点:
1、观察者模式定义了对象之间一对多的关系
2、主题(也就是可观察者)用一个共同的接口来更新观察者
3、观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口
4、使用此模式时,你可从被观察者处推(push)或拉(pull)数据(然而,推的方式被认为更“正确”)
5、有多个观察者时,不可以依赖特定的通知次序。
6、Java有多种观察者模式的实现,包括了能用的java.util.Observable
7、要注意java.util.Observable实现上所带来的一些问题
8、如果有必要的话,可以实现自己的Observable,这并不难,不要害怕
9、Swing大量使用观察者模式,许多GUI框架也是如此
10、此模式也被应用在许多地方,例如:JavaBean、RMI
要点:
1、观察者模式定义了对象之间一对多的关系
2、主题(也就是可观察者)用一个共同的接口来更新观察者
3、观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口
4、使用此模式时,你可从被观察者处推(push)或拉(pull)数据(然而,推的方式被认为更“正确”)
5、有多个观察者时,不可以依赖特定的通知次序。
6、Java有多种观察者模式的实现,包括了能用的java.util.Observable
7、要注意java.util.Observable实现上所带来的一些问题
8、如果有必要的话,可以实现自己的Observable,这并不难,不要害怕
9、Swing大量使用观察者模式,许多GUI框架也是如此
10、此模式也被应用在许多地方,例如:JavaBean、RMI
Mediator(中介者)
定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。
模式的结构:
模式的结构:
- 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
- 具体中介者(ConcreteMediator)角色:实现中介者接口,定义多个同事或一个 List 来管理多个同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
- 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
- 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
Iterator(迭代器)
Visitor(访问者)
定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
模式的结构:
模式的结构:
- 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
- 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
- 抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
- 具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
- 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
Memento(备忘录)
定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
模式的结构:
模式的结构:
- 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
- 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
Interpreter(解释器)
定义:给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。
模式的结构:
解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题。如果碰到对表达式的解释,在 Java 中可以用 Expression4J 或 Jep 等来设计。
模式的结构:
- 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
- 终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
- 非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
- 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
- 客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。
- 当语言的文法较为简单,且执行效率不是关键问题时。
- 当问题重复出现,且可以用一种简单的语言来进行表达时。
- 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释。
解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题。如果碰到对表达式的解释,在 Java 中可以用 Expression4J 或 Jep 等来设计。
0 条评论
下一页