设计模式 Day07 原型模式、建造者模式、策略模式
2021-03-03 本文已影响0人
望穿秋水小作坊
1. 如何判断你已经掌握了某种设计模式?(非常重要)
- ① 这个模式的意图是什么?它解决了什么问题、什么时候可以使用它
- ② 它是如何解决的?掌握它的结构图,记住它的关键代码
- ③ 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
- ④ 这个模式的缺点是什么?在使用时要注意什么
一、对象的克隆-----原型模式
1. 这个模式的意图是什么?它解决了什么问题、什么时候可以使用它
- 什么时候可以使用它
- 原型模式作为一种快速创建大量相同或相似对象的方式,在软件开发中应用较为广泛。
2. 它是如何解决的?掌握它的结构图,记住它的关键代码
image.png- 结构图:
-
Prototype(抽象原型类):
它是声明克隆方法的接口,是所有具有原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。 -
ConcretePrototype(具体原型类):
它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。 -
Client(客户类):
让一个原型对象克隆自身从而创建一个新的对象。由于客户类针对抽象原型类 Prototype 编程,因此用户可以根据需要选择具体原型类,系统具有较好的可扩展性,增加或更换具体原型类都很方便。
3. 至少能够想到它的两个应用实例?一个生活中的,一个软件中的
- 生活中:
CTRL+C
(获取原型类)、CTRL+V
(克隆原型类) - 软件中:实现类似周报模板的功能
4. 这个模式的缺点是什么?在使用时要注意什么
- 缺点:
- ① 需要为每一个类配备一个克隆方法,而该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了
开闭原则
。 - ② 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。
二、复杂对象的组装与创建----建造者模式
1. 这个设计模式的意图是什么?它解决了什么问题、什么时候可以使用它
- 什么时候使用它:
- 它将客户端与包含多个组成部分(或部件)的复杂对象的创建过程分离,客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需要建造者的类型即可。
2. 它是如何解决的?掌握它的结构图,记住它的关键代码
image.png- 结构图:
-
Builder(抽象建造类):
它为创建一个产品 Product 对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类方法是 buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是 getResult(),它们用于返回复杂对象。
-ConcreteBuilder(具体建造者):
它实现了 Builder 接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象。 -
Product(产品角色):
它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。 -
Director(指挥者):
指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。
3. 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
- 生活中的:去 4s 买车,只需要告诉店员车型、颜色等关键信息,就能拿到相应的车,无需关心车是如何构建出来的。
- 软件中的: 通过可配置的头发、肤色、性别等关键信息,生成游戏角色
4. 这个模式的缺点是什么?在使用时要注意什么
- 缺点:
- ① 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制。
- ② 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。
三、算法的封装于切换----策略模式
1. 这个设计模式的意图是什么?它解决了什么问题、什么时候可以使用它
- 什么时候使用它:
-
实现某一个功能有多条途径,每条途径对应一种算法
,此时我们可以使用策略模式
来实现灵活地选择解决途径,也能够方便地增加新的解决途径。
2. 它是如何解决的?掌握它的结构图,记住它的关键代码
image.png-
结构图:
-
Context(环境类):
环境类是使用算法的角色,它在解决某个问题(即实现某个方法)时可以采用多种策略。在环境类中维持一个堆抽象策略类的引用实例,用于定于所采用的的策略。 -
Strategy(抽象策略类):
它为所支持的算法声明了抽象方法,是所有策略类的父类。环境类通过抽象策略类中声明的方法再运行时调用具体策略类中的实现的算法。 -
ConcreteStrategy(具体策略类):
它实现了在抽象策略类中声明的算法,在运行时,具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务处理。 -
关键代码:
abstract class AbstractStrategy {
public abstract void algorithm(); //声明抽象算法
}
class ConcreteStrategyA extends AbstractStrategy {
//算法的具体实现
public void algorithm() {
//算法A
}
}
class Context {
private AbstractStrategy strategy; //维持一个对抽象策略类的引用
public void setStrategy(AbstractStrategy strategy) {
this.strategy= strategy;
}
//调用策略类中的算法
public void algorithm() {
strategy.algorithm();
}
}
……
Context context = new Context();
AbstractStrategy strategy;
strategy = new ConcreteStrategyA(); //可在运行时指定类型
context.setStrategy(strategy);
context.algorithm();
……
3. 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
- 生活中的:旅游可以通过 坐飞机、坐动车、开车、骑自行车等策略
- 软件中的:布局类 LayoutManager 的 FlowLayout、GirdLayout 等等策略
4. 这个模式的缺点是什么?在使用时要注意什么
- 缺点:
- ① 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类。
- ② 无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。
- ③ 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。