设计模式-装饰器模式

170 阅读2分钟

装饰器模式

装饰器模式 ,有人叫包装模式,顾名思义,将一个对象包装一下,哎。它就有个新功能啦。

装饰器模式示例

女娲造人, 先捏出一个泥人,它看起来是个人, 但是不能跑,不能睡觉,不能吃饭,

使用装饰器赋予它这些能力

/**
 * Human 人的接口类
 */
public interface Human{
    void can();  //人能做什么
    void setCapability(String capability); // 赋予人某种能力
}
/**
 * 具体的一个人
 */
public class XiaoMing implements Human{
    List<String> capabilitys = new ArrayList<>();  // 能力列表
    @Override
    public void can() {
        if(capabilitys.isEmpty()){
            System.out.println("我是个泥人,啥也干不了");
        }else{
            System.out.print("我能做:");
            for(String s:capabilitys){
                System.out.print(s);
                System.out.print(",");
            }
            System.out.println();
        }
    }

    @Override
    public void setCapability(String capability) {
        capabilitys.add(capability);
    }
}
/**
 * 能力装饰器抽象类
 */
public abstract class CapabilityDecorator implements Human{

    Human human;

    public CapabilityDecorator(Human human){
        this.human = human;
    }

    @Override
    public void setCapability(String capability) {
        human.setCapability(capability);
    }
}
/**
 * 吃装饰器
 */
public class EatDecorator extends CapabilityDecorator{
    public EatDecorator(Human human) {
        super(human);
        human.setCapability("吃东西");
    }

    @Override
    public void can() {
        human.can();
    }
}
/**
 * 跑装饰器
 */
public class RunDecorator extends CapabilityDecorator{
    public RunDecorator(Human human) {
        super(human);
        human.setCapability("跑");
    }

    @Override
    public void can() {
        human.can();
    }
}
/**
 * 测试类
 */
public class Test {
    public static void main(String[] args){
        Human xiaoMing = new XiaoMing();  //女娲捏出小人
        xiaoMing.can(); // 小明这个时候啥也不会

        xiaoMing = new EatDecorator(xiaoMing); // 赋予他吃东西的能力
        xiaoMing.can(); 

        xiaoMing = new RunDecorator(xiaoMing); // 赋予他跑的能力
        xiaoMing.can();
    }
}

print:

我是个泥人,啥也干不了
我能做:吃东西,
我能做:吃东西,跑,

Java中实现

/**
 * Java IO中的输入流 FilterInputStream 有很多的实现,一个抽象的装饰器有多种实现,之后每次调用都能得到本身的FileInputStream,
 * 在调用GZIPInputStream之后 它的read方法就用于可以解压文件了
 * 在调用BufferedInputStream之后,它的read 方法就可以使用缓冲来提升读取速度
 */
public class Test2 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("test.gz");
        inputStream = new GZIPInputStream(inputStream);
        inputStream = new BufferedInputStream(inputStream);
    }
}

何时使用

当我们想扩展一个对象的行为,或预计未来会多次扩展该对象的行为。那我们在开发的过程中就会不断的修改接口,不断的修改对象的实现,该类也会越来越大。这个时候我们就可以使用装饰器模式,它可以替代继承 来扩展该对象