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

Image

Image

 

 

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

Image

Image

Image

Image

Image

Image

Image

Image

 

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

Image

Image

Image

Image

 

Image

Image

Image

 

Image

Image

Image

 

 

 

 

 

Image

 

Image

Image

ImageImage

Image

 

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

 

1. Component接口

 

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

 

2. ConcreteComponent类

 

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

 

3. Decorator抽象类

 

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

 

4ConcreteDecorator类

 

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

 

 

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

 

Image

Image

 

首先是汽车接口,也就是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();
    }
}

ds或许有人会觉得奇怪,为什么装饰器类也要实现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();
    }
}

Image

Image

Image

 

Image

 

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

 

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

 

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

 

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

Image

Image

 

—————END—————

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值