0、先上需求
需求V1.0:聚会上,男的喝酒,女的喝饮料,用代码实现。
聪明的你,肯定说这个简单。UML类图一画,代码立马跟上。
/**
* @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类图
代码就不给了,从上面的UML类图就可以看出,你设计的思路是采用面向对象的继承。这种方法当然是可以的,但是存在几个问题:
- 如果父类是final的,不允许你继承怎么办?
- 需求一直迭代,某天你的子类越来越多,父类的某个方法需要被改的时候,你所有子类怎么办?
其实有一种设计模式,它的名字叫“装饰者模式”,它能帮你解决以上两个问题。接着往下看~
1、定义
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更为灵活。也可以说,装饰者模式是一种继承关系的替代。
2、UML类图
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、缺点
- 多层装饰逻辑复杂