装饰模式(也叫包装模式)

//汽车接口
public interface Car {

    //驾驶
    void drive();
}
//轿车类
public class Bus implements Car {

    @Override
    public void drive() {
        System.out.println("驾驶轿车");
    }
}

上面我们已经拥有了一个接口还有一个默认实现。包装模式是做的:

首先我们弄一个装饰器,它实现了接口,以组合的方式接收我们的默认实现类

 

/**
 * 装饰器(抽象类)
 */
public abstract class CarDecorate implements Car{

    // 以组合的方式来获取默认实现类
    private Car car;
    public CarDecorate(Car car) {
        this.car = car;
    }

    @Override
    public void drive() {
        car.drive();
    }
}

有了装饰器以后,我们的扩展都可以以装饰器为基础进行扩展,继承装饰器来扩展就好了!

我们想要在开车之前听音乐

/**
 * 继承着装饰器来扩展
 */
public class MusicCar extends CarDecorate {

    public MusicCar(Car car) {
        super(car);
    }

    // 定义想要扩展的功能
    public void listenMusic() {
        System.out.println("开车听音乐");
    }

    //重写驾驶的方法
    @Override
    public void drive() {
        //开车之前听歌
        this.listenMusic();
        super.drive();
    }
}

现在我也想在打开音乐后打开汽车的地图导航,于是我们也继承装饰类来扩展

/**
 * 继承着装饰器来扩展
 */
public class MapCar extends CarDecorate {

    public MapCar(Car car) {
        super(car);
    }

    //开车后打开地图导航
    public void map(){
        System.out.println("开车后打开地图导航");
    }

    @Override
    public void drive() {
        super.drive();
        this.map();
    }
}

可以来测试一下:

//测试类
public class Test {
    public static void main(String[] args) {
        //创建最原始的核心类
        Car car = new Bus();
        //装饰成开车前听音乐,第一次增强
        car = new MusicCar(car);
        //装饰成开车后打开导航,第二次增强
        car = new MapCar(car);
        car.drive();

        //简写
        Car c = new MusicCar(new MapCar(new Bus())); //有没有发现很像IO的写法,其实IO就是装饰模式实现的
        c.drive();
    }
}

输出结果:

 

优点:

  • 装饰类和被装饰类是可以独立的,低耦合的。互相都不用知道对方的存在

  • 装饰模式是继承的一种替代方案,无论包装多少层,返回的对象都是is-a的关系(上面的例子:包装完还是Phone类型)。

  • 实现动态扩展,只要继承了装饰器就可以动态扩展想要的功能了。

缺点:

  • 多层装饰是比较复杂的,提高了系统的复杂度。不利于我们调试~

  注:其实装饰模式或者继承或者代理模式都是对对象的增强

posted @ 2020-06-13 14:57  会偷袭的猫  阅读(249)  评论(0编辑  收藏  举报