六大常用设计模式:四、装饰器模式

4.1、介绍

定义:装饰器模式(Decorator)是指动态地将新功能附加到对象上。在功能扩展方面,它比继承更有弹性,装饰着模式也体现了开闭原则(OCP)。

举例:现有一家咖啡店,售卖的咖啡有ShortBlack、Espresso、LongBlack等,另有调料Chocolate、Milk、Soy等,购买规则是任选一种咖啡,可搭配一种或多种调料,问怎么设计系统得出顾客购买的咖啡详情和价格:顾客要购买2份Chocolate+1份Milk的LongBlack。

这种类型的设计模式属于结构型模式。

4.2、代码支撑

先有抽象类 Drink.java ,里面有字段 describeprice 以及它们的 set/get() 方法,并且有费用计算的抽象方法:

public abstract class Drink {
    
    
    private String describe;
    private float price;
    public String getDescribe() {
    
    
        return describe;
    }
    public void setDescribe(String describe) {
    
    
        this.describe = describe;
    }
    public float getPrice() {
    
    
        return price;
    }
    public void setPrice(float price) {
    
    
        this.price = price;
    }
    public abstract float cost();
}

再用类 Coffee.java 继承 抽象类 Drink.java 。( Coffee.java 类是被装饰者):

public class Coffee extends Drink {
    
    
    @Override
    public float cost() {
    
    
        return super.getPrice();
    }
}

咖啡目前有三种(ShortBlack、Espresso、LongBlack),都继承类 Coffee.java ,重写 describeprice 字段:

第一种咖啡的信息和价格 ShortBlack.java

public class ShortBlack extends Coffee {
    
    
    public ShortBlack() {
    
    
        setDescribe("ShortBlack");
        setPrice(6.0f);
    }
}

第二种咖啡的信息和价格 Espresso.java

public class Espresso extends Coffee {
    
    
    public Espresso() {
    
    
        setDescribe("Espresso");
        setPrice(5.0f);
    }
}

第三种咖啡的信息和价格 LongBlack.java

public class LongBlack extends Coffee {
    
    
    public LongBlack() {
    
    
        setDescribe("LongBlack");
        setPrice(4.0f);
    }
}

下面写装饰者 Decorator.java, 一样 继承 Drink.java ,重写添加了调料的咖啡费用和信息:

public class Decorator extends Drink {
    
    
    private Drink drinkObj;// 被装饰者,即咖啡
    public Decorator(Drink drinkObj) {
    
    
        this.drinkObj = drinkObj;
    }
    @Override
    public float cost() {
    
    
        // 调料自己的价格 + 被装饰者的价格
        return super.getPrice() + drinkObj.cost();
    }
    @Override
    public String getDescribe() {
    
    
        // 调料信息 + 调料价格 + 被装饰者信息
        return super.getDescribe() + "(¥"  + super.getPrice() + ")、" + drinkObj.getDescribe();
    }
}

调料具体有Chocolate、Milk、Soy等,都继承装饰者 Decorator.java ,并创建构造器:

调料Chocolate作为装饰者 Chocolate.java

public class Chocolate extends Decorator {
    
    
    public Chocolate(Drink drinkObj) {
    
    
        super(drinkObj);
        setDescribe("Chocolate");
        setPrice(6.6f);
    }
}

调料Milk作为装饰者 Milk.java

public class Milk extends Decorator{
    
    
    public Milk(Drink drinkObj) {
    
    
        super(drinkObj);
        setDescribe("Milk");
        setPrice(5.5f);
    }
}

调料Soy作为装饰者 Soy.java

public class Soy extends Decorator{
    
    
    public Soy(Drink drinkObj) {
    
    
        super(drinkObj);
        setDescribe("Soy");
        setPrice(4.4f);
    }
}

现在被装饰者(咖啡)和装饰者(调料)都搭建完毕,下面是客户端 Client.java 点餐:

public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 订单:2份Chocolate+1份Milk的LongBlack
        // 选择咖啡LongBlack
        Drink order = new LongBlack();
        System.out.println("需支付总额:¥" + order.cost() + " ,购买信息:" + order.getDescribe());
        //添加调料1份Milk
        order = new Milk(order);
        System.out.println("需支付总额:¥" + order.cost() + " ,购买信息:" + order.getDescribe());
        // 添加2份Chocolate
        order = new Chocolate(order);
        System.out.println("需支付总额:¥" + order.cost() + " ,购买信息:" + order.getDescribe());
        order = new Chocolate(order);
        System.out.println("需支付总额:¥" + order.cost() + " ,购买信息:" + order.getDescribe());

    }
}

控制台输出结果:

在这里插入图片描述

如果店铺进货了其他咖啡,那么只需要给该咖啡创建一个类,这个类继承 Coffee.java ,且生成构造器设置该咖啡的信息和价格。

4.3、总结

装饰器模式,是一种在运行期动态给某个对象的实例增加功能的方法。

就增加功能来说,相比生成子类更为灵活。但它有许多子类,过度使用会增加程序得复杂性。

装饰器模式的目的,就是把一个一个的附加功能,用Decorator的方式给一层一层地累加到原始数据源上,最终,通过组合获得我们想要的功能。

猜你喜欢

转载自blog.csdn.net/weixin_60808029/article/details/122607463
今日推荐