当前位置: 移动技术网 > IT编程>软件设计>设计模式 > 设计模式 - 装饰者模式详解

设计模式 - 装饰者模式详解

2020年04月04日  | 移动技术网IT编程  | 我要评论

基本定义

装饰者模式属于结构型模式,它可以动态的将新功能附加到对象上,同时又不改变其结构。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)。

模式结构

装饰者和被装饰者有相同的超类型,因为装饰者和被装饰者必须是一样的类型,利用继承是为了达到类型的匹配,而不是利用继承获取行为

  • component:装饰者和被装饰者共同的父类,是一个接口或者抽象类,用来定义基本行为
  • concretecomponent:定义具体对象,即被装饰者
  • decorator:抽象装饰者,继承自 component,从外类来扩展 concretecomponent。对于 concretecomponent来说,不需要知道decorator的存在,decorator 是一个接口或抽象类
  • concretedecorator:具体装饰者,用于扩展 concretecomponent

举例说明

在咖啡店客人想点一杯加两份糖一份牛奶的摩卡咖啡,各个商品的价格如下,我们需要根据用户点的咖啡、加的配料,动态的计算价格

商品 价格
拿铁咖啡(lattecoffee) 4.5
摩卡咖啡(mochacoffe) 5.5
糖(sugar) 1.0
牛奶(milk) 2.0

「实体类」 coffee

public abstract class coffee{
    public string des = "咖啡"; //描述
    private float price = 0.0f; //价格

    protected abstract float cost(); //计算费用
    
    //省略getter setter方法
}

「被装饰者」lattecoffee

public class lattecoffee extends coffee{
    public lattecoffee() {
        setdes("拿铁咖啡");
        setprice(4.5f);
    }

    @override
    protected float cost() {
        return getprice();
    }
}

「被装饰者」mochacoffee

public class mochacoffee extends coffee {
    public mochacoffee() {
        setdes("摩卡咖啡");
        setprice(5.5f);
    }

    @override
    protected float cost() {
        return getprice();
    }
}

「抽象装饰者」decorator

public class decorator extends coffee {

    private coffee coffee;

    public decorator(coffee drink) {
        this.coffee = drink;
    }

    @override
    protected float cost() {
        return getprice() + coffee.cost();
    }

    @override
    public string getdes() {
        return coffee.getdes() + "加" + super.getdes();
    }
}

「具体装饰者」sugardecorator

public class sugardecorator extends decorator{
    public sugardecorator(coffee coffee) {
        super(coffee);
        setdes("糖");
        setprice(1.0f);
    }
}

「具体装饰者」milkdecorator

public class milkdecorator extends decorator{
    public milkdecorator(coffee coffee) {
        super(coffee);
        setdes("牛奶");
        setprice(2.0f);
    }
}

「测试类」client

public class client {
    /**
     * 点一杯 加两份糖一份牛奶的摩卡咖啡
     */
    @test
    public void test01() {
        coffee order = new mochacoffee();
        system.out.println(order.getdes() + ",价格:" + order.cost());
        //加两份糖
        order = new sugardecorator(new sugardecorator(order));
        system.out.println(order.getdes() + ",价格:" + order.cost());
        //加一份牛奶
        order = new milkdecorator(order);
        system.out.println(order.getdes() + ",价格:" + order.cost());
    }
}

「结果」result

摩卡咖啡,价格:5.5
摩卡咖啡加糖加糖,价格:7.5
摩卡咖啡加糖加糖加牛奶,价格:9.5

在 java io 流中的应用

在上图所示的关系中

  • 实体类是 inputstream
  • 被装饰者是fileinputstream、stringbufferinputstream、bytearrayinputstream
  • 抽象装饰者是filterinputstream
  • 具体装饰者是bufferinputstream、datainputstream、linenumberinputstream

具体使用如下:

bufferedinputstream bis = new bufferedinputstream(new fileinputstream("g:\\a.txt"));

装饰者模式总结

1、利用继承设计子类,只能在编译时静态决定,并且所有子类都会继承相同的行为;利用组合扩展对象,就可以在运行时动态的进行扩展。

2、装饰者和被装饰者对象有相同的超类型,所以在任何需要原始对象(被装饰者)的场合,都可以用装饰过的对象代替原始对象。

3、可以用一个或多个装饰者包装一个对象(被装饰者)。

4、装饰者可以在所委托的装饰者行为之前或之后加上自己的行为,以达到特定的目的。

5、被装饰者可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。

6、装饰者会导致出现很多小对象,如果过度使用,会让程序变得复杂。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网