一 . 模式动机
-
一般有两种方式可以给一个类或对象增加行为:
- 继承:是给现有类增加功能的一种有效途径,这是静态的,因为用户不能控制增加行为的方式和时机。
- 关联(组合):即将一个类嵌入另一个对象中,由另一个对象决定是否调用嵌入对象的行为以便扩展自己的行为,我们成这个嵌入的对象为装饰器。
-
这个模式就是以对客户透明的方式动态给一个对象附加上更多功。
二 . 模式定义
- 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。属于结构型模式。
三 . 模式结构
(图片来源于网络)
- Component:抽象构件
- ConcreteComponent:具体构件
- Decorator:抽象装饰类
- ConcreteDecorator:具体装饰类
四 . 模式分析
- 与继承相比,关联的优势是不会破坏类的封装性,继承是一种耦合程度大的静态关系,无法在程序运行时动态扩展,缺点是要很多的类。
五 . 模式实例
-
车的普通功能是陆地上跑,我们可以适用装饰器模式,给它新增天上飞和海里游的功能。
-
抽象构件ICar和具体构件Car
interface ICar {
void run();
}
public class Car implements ICar {
@Override
public void run() {
System.out.println("汽车会跑");
}
}
- 抽象装饰类SuperCar和具体装饰类FlayCar,WaterCar
public class SuperCar implements ICar{
protected ICar car;
public SuperCar(ICar car){
this.car = car;
}
@Override
public void run() {
car.run();
}
}
class WaterCar extends SuperCar{
public WaterCar(ICar car) {
super(car);
}
public void Swim(){
System.out.println("会游泳");
}
public void run(){
super.run();
this.Swim();
}
}
class FlayCar extends SuperCar{
public FlayCar(ICar car) {
super(car);
}
public void flay(){
System.out.println("会飞");
}
public void run(){
super.run();
this.flay();
}
}
- 测试类
public class Client {
public static void main(String[] args) {
SuperCar superCar =new WaterCar(new FlayCar(new Car()));
superCar.run();
}
}
- 测试结果
E:\Java\jdk1.8.0_171\bin\java.exe "-javaagent:E:\idea\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=57596:E:\idea\IntelliJ IDEA 2019.1.3\bin" -Dfile.encoding=UTF-8 -classpath "E:\Java\jdk1.8.0_171\jre\lib\charsets.jar;E:\Java\jdk1.8.0_171\jre\lib\deploy.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;E:\Java\jdk1.8.0_171\jre\lib\javaws.jar;E:\Java\jdk1.8.0_171\jre\lib\jce.jar;E:\Java\jdk1.8.0_171\jre\lib\jfr.jar;E:\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;E:\Java\jdk1.8.0_171\jre\lib\jsse.jar;E:\Java\jdk1.8.0_171\jre\lib\management-agent.jar;E:\Java\jdk1.8.0_171\jre\lib\plugin.jar;E:\Java\jdk1.8.0_171\jre\lib\resources.jar;E:\Java\jdk1.8.0_171\jre\lib\rt.jar;E:\Design pattern\out\production\Design pattern" Decorator.Client
汽车会跑
会飞
会游泳
Process finished with exit code 0
六 . 模式优缺点
- 优点
- 比继承更灵活
- 可以通过动态方式来扩展功能
- 符合“开闭原则”
- 缺点
- 比继承要增加很多类,增加系统复杂度。
- 比继承更加灵活,也意味着装饰器模式比继承更加容易出错,排错也很困难。
七 . 适用场景
- 需要动态的给一个对象增加功能
- 当一个类不能被继承时,可以使用装饰器模式
八 . 模式应用
- java的IO流类