浅谈装饰者模式

0、先上需求

需求V1.0:聚会上,男的喝酒,女的喝饮料,用代码实现。
聪明的你,肯定说这个简单。UML类图一画,代码立马跟上。

image.png

/**
 * @author xiaoqqq by 2020/1/2 22:49
 * @desc: 人
 */
public abstract class Person {

    /**
     * 具体喝啥,子类自己去实现
     */
    public abstract void drink();
}
/**
 * @author xiaoqqq by 2020/1/2 22:51
 * @desc: 男性
 */
public class Male extends Person {

    @Override
    public void drink() {
        System.out.println("喝酒");
    }
}

/**
 * @author xiaoqqq by 2020/1/2 22:51
 * @desc: 女性
 */
public class Females extends Person {

    @Override
    public void drink() {
        System.out.println("喝饮料");
    }
}

完工,你以为你写完了,实际上也只是你觉得写完了。

需求V2.0,所有会唱歌的男同胞,喝酒之前唱首歌,不会唱歌的男同胞,喝酒之前说个笑话。
聪明的你,心想简单!马上安排……

需求V2.0 UML类图
image.png

代码就不给了,从上面的UML类图就可以看出,你设计的思路是采用面向对象的继承。这种方法当然是可以的,但是存在几个问题:

  • 如果父类是final的,不允许你继承怎么办?
  • 需求一直迭代,某天你的子类越来越多,父类的某个方法需要被改的时候,你所有子类怎么办?

其实有一种设计模式,它的名字叫“装饰者模式”,它能帮你解决以上两个问题。接着往下看~

1、定义

动态的给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更为灵活。也可以说,装饰者模式是一种继承关系的替代。

2、UML类图

image.png

3、代码实现

Step1: 定一个抽象的组件类

/**
 * @author xiaoqqq by 2020/1/2 22:49
 * @desc: 人
 */
public abstract class Person {

    /**
     * 具体喝啥,子类自己去实现
     */
    public abstract void drink();
}

Step2: 定义一个抽象的装饰者类

/**
 * @author xiaoqqq by 2020/1/3 00:10
 * @desc: 抽象的装饰者类
 */
public abstract class Decorator extends Person {

    private Person person;

    public Decorator(Person male) {
        this.person = male;
    }

    @Override
    public void drink() {
        person.drink();
    }
}

Step3: 定一个具体的被装饰者类(组件类的具体实现类)

/**
 * @author xiaoqqq by 2020/1/3 00:11
 * @desc: 装饰者的具体实现类,实现喝酒之前先唱歌
 */
public class CanSingMale extends Decorator {

    public CanSingMale(Person person) {
        super(person);
    }

    @Override
    public void drink() {
        sing();
        super.drink();
    }

    private void sing() {
        System.out.println("唱歌");
    }

}

Step4: 客户端调用

/**
 * @author xiaoqqq by 2020/1/2 22:52
 * @desc: 程序入口
 */
public class TestMain {

    public static void main(String[] args) {
        Person male = new Male();
        Decorator decorator = new CanSingMale(male);
        decorator.drink();
    }
}

4、总结

4.1、优点
  • 继承方案的替代,避免类爆炸。
  • 就增强功能而言,比类继承更为灵活,可扩展性更高。
4.2、缺点
  • 多层装饰逻辑复杂

你可能感兴趣的:(浅谈装饰者模式)