设计模式 - 装饰者模式

324

一、需求

有一个人,战斗力只有 2 万最高,需要通过变身,来增强自己的战斗力,变身为:

  • 超级赛亚人一,提高到 20 万战斗力
  • 超级赛亚人二,提高到 200 万战斗力
  • 超级赛亚人三,提高到 2000 万战斗力
public interface Biology {
    void feature();
}
public class Human implements Biology{
    @Override
    public void feature() {
        System.out.println("人类特性:战斗力小于 2 万");
    }
}

可以有哪些方式来增强?

二、继承增强

2.1 思路

每一个增强类都可以通过继承原有类从而拓展原有类功能

超级塞亚人一增强了人类

public class SuperSaiyanI extends Human{
    @Override
    public void feature() {
        super.feature();
        System.out.println("超级赛亚人一特性:战斗力小于 20 万");
    }
}

超级赛亚人二增强了超级赛亚人一

public class SuperSaiyanII extends SuperSaiyanI {
    @Override
    public void feature() {
        super.feature();
        System.out.println("超级赛亚人二特性:战斗力小于 200 万");
    }
}

超级赛亚人三继承了超级赛亚人二

public class SuperSaiyanIII extends SuperSaiyanII {
    @Override
    public void feature() {
        super.feature();
        System.out.println("超级赛亚人三特性:战斗力小于 2000 万");
    }
}

2.2 结果

测试一下增强效果:

public class Test {
    public static void main(String[] args) {
        Human human = new Human(); //原始人类
        human.feature();
        System.out.println();

        human = new SuperSaiyanI();//原始人类到超级赛亚人一
        human.feature();
        System.out.println();

        human = new SuperSaiyanII();//原始人类到超级赛亚人二
        human.feature();
        System.out.println();

        human = new SuperSaiyanIII();//原始人类到超级塞亚人三
        human.feature();
        System.out.println();
    }
}

输出:

人类特性:战斗力小于 2 万

人类特性:战斗力小于 2 万
超级赛亚人一特性:战斗力小于 20 万

人类特性:战斗力小于 2 万
超级赛亚人一特性:战斗力小于 20 万
超级赛亚人二特性:战斗力小于 200 万

人类特性:战斗力小于 2 万
超级赛亚人一特性:战斗力小于 20 万
超级赛亚人二特性:战斗力小于 200 万
超级赛亚人三特性:战斗力小于 2000 万

赛亚人一到三增强时,省略过程?无非就是继承的时候不调用 super.feature() 可以在增强类中直接写增强结果

2.3 分析

通过继承可以增强原有类的功能,但过多的增强需求会导致拓展功能类继承关系越来越多层,耦合度增加程度很高,一个类修改,会影响许多类被更改,有个不大官方的词管这种现象叫做 “类爆炸”

所以,长远考虑,这种方式不适合用来增强拓展原有类,因为耦合度太高了

三、装饰增强

3.1 思路

创建一个装饰器(或许代入这里的场景就是所谓的变身器了 XD),将功能拓展类的增强功能 “装饰” 到原有类上,具体做法如下:

装饰器:

public abstract class HumanDecorator implements Biology{

    //要装饰的人类
    private Biology human;

    public HumanDecorator(Biology human) {
        this.human = human;
    }

    @Override
    public void feature() {
        human.feature();
    }
}

人类:

public class Human implements Biology{
    @Override
    public void feature() {
        System.out.println("人类特性:战斗力小于 2 万");
    }
}

超级赛亚人一:

public class SuperSaiyanI extends HumanDecorator {
    public SuperSaiyanI(Biology human) {
        super(human);
    }

    public void superSaiyanFeature() {
        System.out.println("超级赛亚人一特性:战斗力小于 20 万");
    }

    @Override
    public void feature() {
        super.feature();
        superSaiyanFeature();
    }
}

超级赛亚人二:

public class SuperSaiyanII extends HumanDecorator {

    public SuperSaiyanII(Biology human) {
        super(human);
    }

    public void superSaiyanIIFeature(){
        System.out.println("超级赛亚人二特性:战斗力小于 200 万");
    }

    @Override
    public void feature() {
        super.feature();
        superSaiyanIIFeature();
    }
}

超级赛亚人三:

public class SuperSaiyanIII extends HumanDecorator {
    public SuperSaiyanIII(Biology human) {
        super(human);
    }

    public void superSaiyanIIIFeature() {
        System.out.println("超级赛亚人三特性:战斗力小于 2000 万");
    }

    @Override
    public void feature() {
        super.feature();
        superSaiyanIIIFeature();
    }
}

3.2 结果

测试一下增强效果:

public class Test {
    public static void main(String[] args) {
        //初始化普通人
        Biology human = new Human();
        human.feature();
        System.out.println();

        //人类变身超级赛亚人一
        human = new SuperSaiyanI(human);
        human.feature();
        System.out.println();


        //超级赛亚人一变身超级赛亚人二
        human = new SuperSaiyanII(human);
        human.feature();
        System.out.println();

        //超级赛亚人二变身超级赛亚人三
        human = new SuperSaiyanIII(human);
        human.feature();

    }
}

输出:

人类特性:战斗力小于 2 万

人类特性:战斗力小于 2 万
超级赛亚人一特性:战斗力小于 20 万

人类特性:战斗力小于 2 万
超级赛亚人一特性:战斗力小于 20 万
超级赛亚人二特性:战斗力小于 200 万

人类特性:战斗力小于 2 万
超级赛亚人一特性:战斗力小于 20 万
超级赛亚人二特性:战斗力小于 200 万
超级赛亚人三特性:战斗力小于 2000 万

3.3 分析

原本需要一层又一层继承,一层又一层的堆积,才能实现新的功能拓展类

现在,不再有那么多层的继承关系,功能拓展类继承了装饰器,具有 “装饰” 的性质了,建立了新的功能拓展类,将原有类通过构造器传给功能拓展类,可以将旧类的功能装饰给功能拓展类,那么原有对象就有了新的功能

这个过程,原有对象的功能是通过不断 “装饰” 来得到的,功能拓展类间的耦合度大大降低,因为需求实在变动很大,直接删掉,重写一个新的功能类都可以,其他的功能拓展类却可以不变

四、总结

继承类增强的过程其实可以一句话解决:

Human human = new SuperSaiyanIII();
human.feature();

装饰器增强的过程其实也可以一句话解决:

Biology human = new SuperSaiyanIII(new SuperSaiyanII(new SuperSaiyanI(new Human())));
human.feature();

结合分析,无论是继承增强还是装饰器增强,都是要用到多态上转型为根本来操作的

这个过程中:

  • 继承说白了就是不断继承,添加新功能..
  • 装饰器说白了就是不断更新旧的原有对象,并结合旧的原有对象,添加新功能

五、应用

Java I/O 流:

//例一:控制台读取字符串
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

//例二:读取磁盘文件流
BufferedInputStream bis = 
    					new BufferedInputStream(
    					new FileInputStream(
                        new File("/home/user/abc.txt")));