likes
comments
collection
share

漫画设计模式:什么是“装饰器模式”?

作者站长头像
站长
· 阅读数 1

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

————— 第二天 —————

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

————————————

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

装饰器模式都包含哪些核心角色呢?

1. Component接口

在我们上面的例子中,Component接口相当于汽车接口,所有的被包装类、包装类,都继承于这个接口。

2. ConcreteComponent类

ConcreteComponent类是被包装的实现类。在例子中,奔驰汽车、宝马汽车、特斯拉汽车都属于这个角色。

3. Decorator抽象类

所有的包装类,都继承自Decorator抽象类,而Decorator类又实现了Component接口,这么做是为了实现多层嵌套包装。

4. ConcreteDecorator类

具体的包装类,用于扩充被包装类的功能,比如例子中的自动驾驶功能、飞行功能扩展。

这四大核心角色的关系是怎样的呢?我们可以用装饰器模式的UML类图来表达:

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

首先是汽车接口,也就是Component这个角色,里面定义了run这个行为:

public interface Car { void run(); }

接下来是各种汽车的实现类,也就是ConcreteComponent角色,不同的汽车对于run行为有着不同的实现:

public class BenzCar implements Car{ @Override public void run() { System.out.println("奔驰开车了!"); } } public class BmwCar implements Car{ @Override public void run() { System.out.println("宝马开车了!"); } } public class TeslaCar implements Car{ @Override public void run() { System.out.println("特斯拉开车了!"); } }

下面是装饰器的抽象类,也就是Decorator角色,这个角色包含了被装饰的成员对象:

public class CarDecorator implements Car { protected Car decoratedCar; public CarDecorator(Car decoratedCar){ this.decoratedCar = decoratedCar; } public void run(){ decoratedCar.run(); } }

或许有人会觉得奇怪,为什么装饰器类也要实现Car接口呢?这正是装饰器模式的灵活之处。

继承自Car接口,可以让每一个装饰器本身也可以被更外层的装饰器所包装,包装的方式就是把Car对象作为参数,传入到外层装饰器的构造函数当中。

接下来是具体的装饰器实现类,也就是ConcreteDecorator角色。这些装饰器同样实现了run的行为,一方面会调用被包装对象的run方法,一方面会进行某些扩展操作(比如自动驾驶、飞行):

public class AutoCarDecorator extends CarDecorator { public AutoCarDecorator(Car decoratedCar){ super(decoratedCar); } @Override public void run(){ decoratedCar.run(); autoRun(); } private void autoRun(){ System.out.println("开启自动驾驶"); } } public class FlyCarDecorator extends CarDecorator { public FlyCarDecorator(Car decoratedCar){ super(decoratedCar); } @Override public void run(){ decoratedCar.run(); fly(); } private void fly(){ System.out.println("开启飞行汽车模式"); } }

最后,是我们的客户端类。客户端类负责创建被包装对象和装饰者,并决定如何进行包装和执行:

public class Client { public static void main(String[] args) { Car benzCar = new BenzCar(); Car bmwCar = new BmwCar(); Car teslaCar = new TeslaCar(); //创建自动驾驶的奔驰汽车 CarDecorator autoBenzCar = new AutoCarDecorator(benzCar); //创建飞行的、自动驾驶的宝马汽车 CarDecorator flyAutoBmwCar = new FlyCarDecorator(new AutoCarDecorator(bmwCar)); benzCar.run(); bmwCar.run(); teslaCar.run(); autoBenzCar.run(); flyAutoBmwCar.run(); } }

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

以输入流为例,为了满足不同输入场景,JDK设计了多种多样的输入流,包括ByteArrayInputStream、FileInputStream等等。

这些输入流都继承自共同的抽象类:InputStream。

与此同时,为了给这些输入流带来功能上的扩展,JDK设计了一个装饰器类,FilterInputStream。该类继承自InputStream,并且“组合”了InputStream成员对象。

从FilterInputStream类派生出了许多装饰器子类,包括BufferedInputStream,DataInputStream等等,分别提供了输入流缓冲,以及从输入流读取Java基本数据类型等额外功能。

漫画设计模式:什么是“装饰器模式”?

漫画设计模式:什么是“装饰器模式”?

喜欢本文的朋友,欢迎关注微信公众号 程序员小灰,收看更多精彩内容