设计模式-9-装饰者模式

定义

动态地将责任附加到对象上,若要扩展功能,装饰者比继承更有弹性

角色

在这里插入图片描述
装饰者将被装饰聚合到自己内部,双方都继承共同的抽象方法,往往是被装饰者只需要完成自己的本质工作,装饰者在集成的被装饰者功能基础之上添加自己的逻辑。下面以饮品店咖啡和咖啡配料组合例子作为案例说明

饮品店案例

  • UML
    在这里插入图片描述
public abstract class Drink {
    private String des;
    private float  price = 0f;

    // setter getter 省略

    public abstract float cost();

}
public class Coffee extends Drink {

    // 被装饰者只需要完成自己本身的价格
    @Override
    public float cost() {
        return super.getPrice();
    }

    // 被装饰者只需要完成自己本身的价格
    @Override
    public String getDes() {
        return super.getDes() + ":" + super.getPrice();
    }
}
public class Decorator extends Drink {
    //装饰者将被装饰者聚合进来作为自己行为的基础
    private Drink obj;

    public Decorator(Drink obj) {
        this.obj = obj;
    }
    //obj.getDes()在被装饰者基础之上进行装饰自己行为super.getDes() + ":" + super.getPrice()
    @Override
    public String getDes() {
        return super.getDes() + ":" + super.getPrice() + " && " + obj.getDes();
    }

    @Override
    public float cost() {
        return super.getPrice() + obj.cost();
    }

}
// 被装饰者
// 以拿铁咖啡为例 作为被装饰者定义自己行为即可
public class Latte extends Coffee {
    public Latte() {
        super.setDes(" Latte ");
        super.setPrice(6.0f);
    }
}
// ------------作为装饰者的具体实现-----------------
public class Milk extends Decorator {
    public Milk(Drink obj) {
        super(obj);
        super.setDes("牛奶");
        super.setPrice(2.0f);
    }
}
public class Chocolate extends Decorator {

    public Chocolate(Drink obj) {
        super(obj);
        super.setDes(" 巧克力 ");
        super.setPrice(2.0f);
    }

}
// ----------------客户端----------------
public static void main(String[] args) {
        Drink order = new Latte();
        System.out.println("order明细:" + order.getDes() + "\n" + "order总价:" + order.cost());
        // 此时被装饰者是Latte
        order = new Chocolate(order);
        // 被装饰者是加了chocolate的latte
        order = new Milk(order);
        System.out.println("order明细:" + order.getDes() + "\n" + "order总价:" + order.cost());
    }

java中的装饰者模式InputStream

在这里插入图片描述

  • 比如我们想扩展一个把字符转换成小写的inputStream,我们只需要扩展一个继承FilterInputStream的具体装饰者(这里命令为LowerCaseInputStream)代码如下:
public class LowerCaseInputStream extends FilterInputStream {
    protected LowerCaseInputStream(InputStream in) {
        super(in);
    }
    @Override
    public int read() throws IOException {
        // super.read()方法执行了in.read();即完成了被装饰者的功能
        int c = super.read();
        // 在被装饰者功能的基础之上增加其他行为
        return (c == -1 ? c : Character.toLowerCase((char) c));
    }
}
//----客户端调用---
public class InputStreamMain {
    public static void main(String[] args) {
        int c;
        try {
            InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("./test")));
            while ((c = in.read()) >= 0) {
                System.out.print((char) c);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
// 输入:I know the Decorator Pattern therefore I RULE!
// 输出:i know the decorator pattern therefore i rule!

对比适配器、外观、装饰者

  • 适配器:将一个对象包装起来以改变其接口
  • 外观:将一群对象“包装”起来以简化其接口
  • 装饰者:将一个对象包装起来以增加新的行为和责任

参考

《Head First设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值