Head First Design Patterns——装饰者模式

基本介绍:
装饰者模式:动态的将新功能附加到对象上,在对象功能扩展方面,它比继承更具有弹性,装饰者模式也体现了开闭原则(ocp),装饰者模式也可以理解为包装模式。

例如:我们要寄一个手机,发快递我们的操作应该如下 :

①把手机用防震膜包裹起来,这是第一层的装饰
在这里插入图片描述
②接下来我们得用快递盒进行包装
在这里插入图片描述
③最后再用塑料袋子封装好
在这里插入图片描述

这样一个手机就完成了包装,装饰者模式就是这样的原理,下面来看具体的说明:
  • 类图表示
    在这里插入图片描述

(1)Component

定义一个抽象类,用于接收动态添加的需求。

(2)ConcreteComponent

ConcreteComponent是我们要动态加上新行为的对象。

(3)Decorator

每一个装饰者都持有一个构件(Component)对象的实例,

也就是说,装饰者有一个实例变量以保存某个Component的引用,

(4)ConcreteDecorator

真正的装饰者,负责给对象添加新的方法和行为。

第一个例子:

被装饰者抽象类:Beverage
被装饰者:Espresso,HouseBlend
装饰者抽象类:CondimentDecorator
装饰者:Mocha

  • 具体实现代码
/**
 * 被装饰者的抽象类:饮料
 */
public abstract class Beverage {

    String description = "Unknown Beverage";

    //成本
    public abstract double cost();

    //得到描述信息
    public String getDescription(){
        return description;
    }
}

/**
 * 被装饰者:浓咖啡
 */
public class Espresso extends Beverage {

    public Espresso() {
        description = "Espresso";
    }

    @Override
    public double cost() {
        return 2;
    }
}

/**
 * 被装饰者:混合咖啡
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "House Blend";
    }

    @Override
    public double cost() {
        return 1;
    }
}

/**
 * 装饰者的抽象类:调料
 */
public abstract class CondimentDecorator extends Beverage {

    public abstract String getDescription();

    @Override
    public double cost() {
        return 0;
    }
}

/**
 * 装饰者:摩卡
 */
public class Mocha extends CondimentDecorator {

	//聚合被装饰者,可以传入实现Beverage接口的所有对象
    Beverage beverage;
	//构造器,初始化beverage
    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription()+",Mocha";
    }

    @Override
    public double cost() {
    	//调用被装饰者的成本,加上装饰者的成本
        return 3 + beverage.cost();
    }
}

/**
 * 测试
 */
public class CoffeeTest {
    public static void main(String[] args) {

        Beverage beverage = new Espresso();
        //一杯浓咖啡为2元
        System.out.println(beverage.getDescription()+","+beverage.cost());

        Beverage beverage1 = new HouseBlend();
        //一杯混合咖啡(1)加摩卡(3)为4元
        // 在单个混合咖啡中包装了摩卡
        beverage1 = new Mocha(beverage1);
        System.out.println(beverage1.getDescription()+","+beverage1.cost());

        //一杯混合咖啡(1)加摩卡(3)加摩卡(3)为7元
        //可以在包装好的基础上再次进行包装
        beverage1 = new Mocha(beverage1);
        System.out.println(beverage1.getDescription()+","+beverage1.cost());
    }
}
  • 运行结果
    在这里插入图片描述

我们发现,写的包装起作用了,可以实现包装功用了!

  • 类图形式
    在这里插入图片描述

第二个例子:

  • 结构图
    在这里插入图片描述
  • 代码实现
/**
 * 被装饰者抽象类
 */
public abstract class Drink {

    public String des;//描述
    private float price = 0.0f;

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    //计算费用的抽象 方法
    public  abstract float cost();
}

/**
 * 缓冲层
 */
public class Coffee extends Drink {
    @Override
    public float cost() {
        return super.getPrice();
    }
}

/**
 * 被装饰者:意大利咖啡
 */
public class Espresso extends Coffee {

    public Espresso(){
        setDes("意大利咖啡");
        setPrice(6.0f);
    }
}


/**
 * 装饰者抽象类:
 */
public class Decorator extends Drink {
    private Drink obj;

    public Decorator(Drink obj) {//组合
        this.obj = obj;
    }

    @Override
    public float cost() {
        //getPrice自己的价格
        return super.getPrice() + obj.cost();
    }


    public String getDes(){
        //obj.getDes()被装饰者的信息
        return super.des+" "+super.getPrice()+"&&"+obj.getDes();
    }
}


/**
 * 被装饰者:LongBlack
 */
public class LongBlack extends Coffee {
    public LongBlack() {
        setDes("LongBlack");
        setPrice(5.0f);
    }
}

/**
 * 被装饰者:ShortBlack
 */
public class ShortBlack extends Coffee {
    public ShortBlack() {
        setDes("ShortBlack");
        setPrice(4.0f);
    }
}

/**
 * 装饰者:
 */
public class Milk extends Decorator {
    public Milk(Drink obj) {
        super(obj);
        setDes("牛奶");
        setPrice(2.0f);
    }

}

/**
 * 装饰者:
 */
public class Soy extends Decorator {
    public Soy(Drink obj) {
        super(obj);
        setDes("豆浆");
        setPrice(1.5f);
    }
}

/**
 * 装饰者:
 */
public class Chocolate extends Decorator {

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

public class CoffBar {
    public static void main(String[] args) {

        //1.点一份LongBlank
        Drink order = new LongBlack();
        System.out.println("费用1="+order.cost());
        System.out.println("描述="+order.getDes());
        
        //2.加一份牛奶
        order = new Milk(order);
        System.out.println("加入一份牛奶后的费用1="+order.cost());
        System.out.println("描述="+order.getDes());

        //3.加入一份巧克力
        order = new Chocolate(order);
        System.out.println("加入一份牛奶,一份巧克力后的费用1="+order.cost());
        System.out.println("描述="+order.getDes());
    }
}
  • 运行结果
    在这里插入图片描述
  • 类图形式
    在这里插入图片描述

java I/O

在这里插入图片描述

  • 从JDK源码中我们可以发现
//装饰者抽象类类继承了被装饰者:InputStream 
public class FilterInputStream extends InputStream {
    /**
     * The input stream to be filtered.
     */
     //聚合了抽象组件componment
    protected volatile InputStream in;

    /**
     * Creates a <code>FilterInputStream</code>
     * by assigning the  argument <code>in</code>
     * to the field <code>this.in</code> so as
     * to remember it for later use.
     *
     * @param   in   the underlying input stream, or <code>null</code> if
     *          this instance is to be created without an underlying stream.
     */
    //利用构造方法初始化InputStream 
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
----------------------------------------------------------------------------------------
//被装饰者继承抽象类InputStream
public
class FileInputStream extends InputStream
{
    .......
}
----------------------------------------------------------------------------------------
//实际的装饰者继承装饰者抽象类
public
class DataInputStream extends FilterInputStream implements DataInput {

    ...
 }

小结:

1.装饰者模式意味着一群装饰者类,这些类用来包装具体组件。
2.装饰者类反映 出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现)。
3.装饰者可以在被装饰者的行为前面/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
4.你可以用无数个装饰者包装一个组件。
5.装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值