Head First -装饰器模式

装饰器模式:
动态地给对象添加额外的责任,就好比房子进行装修一样,房架子就好比要装饰的对象,我把拿过来一顿装饰,可能是增加了很多方法,可能是修改了属性值,让这个对象更丰富起来
条件:
必须具有一个装饰对象

装饰者与被装饰者必须具有相同类型,也就是继承了相同父类,这里的继承不是继承行为,而是继承类型

完美采用了开放-关闭原则:针对扩展开放,对修改关闭

类图:
这里写图片描述


现有小需求如下:
给星巴兹咖啡更新订单系统,是的,是星巴兹不是星巴克,咖啡暂定四种,HouseBlend,DarkRoast,Decaf,Espresso,调料四种Soy(豆浆)、Mocha(摩卡)、Milk(牛奶)、Whip(奶泡);但是组合有很多种,一种咖啡可以加很多调料,随意组合,系统来显示都点了啥,总共多少钱

类图如下:
这里写图片描述
1.我们先来写咖啡的抽象类

//咖啡基类抽象类
abstract class Beverage{
    String description = "Unknown Beverage";//定义了一个属性用来描述你都点了啥
    public String getDescription(){
        return description;
    }
    public abstract double cost();//此处定义抽象方法让子类去实现
}

2.然后写装饰器的抽象类

//咖啡装饰抽象类 继承自Beverage 这样他的子类(具体装饰器)就也继承了Beverage,与被装饰对象具有相同父类
abstract class CondimentDecorator extends Beverage{
    public abstract String getDescription();
}

3.然后我们来写具体的咖啡

//具体饮料
class Espresso extends Beverage {
    public Espresso(){//构造函数的时候添加自己的描述
        description = "Espresso";
    }
    public double cost(){//定义啥也不加多少钱
        return 2.5;
    }
}
//咖啡 同上
class HouseBlend extends Beverage {
    public HouseBlend(){
        description = "HouseBlend";
    }
    public double cost(){
        return 3.3;
    }
}
//DarkRoast
class DarkRoast extends Beverage{
    public DarkRoast(){
        description = "DarkRoast";
    }
    public double cost(){
        return 6.6;
    }
}
//Decaf
class Decaf extends Beverage{
    public Decaf(){
        description = "Decaf";
    }
    public double cost(){
        return 7.7;
    }
}

4.重点来了,具体装饰器在这实现,也就是每种调料是怎么装饰这些咖啡的

//摩卡装饰器
class Mocha extends CondimentDecorator{//继承抽象装饰器也就继承了Beverage
    Beverage beverage;//声明一个父类对象
    public Mocha(Beverage beverage){
        this.beverage = beverage;//构造函数时把传过来的对象赋给当前beverage对象,
                                //传过来的参数也就是要装饰的对象,是具体的咖啡对象向上转型为父类型Beverage类型的对象,
                                //这也就说明了为什么装饰者要与被装饰者具有相同超类,不同的话你这对象赋值赋不过去啊
        description = beverage.getDescription() +"、Mocha";//给继承过来的父类属性值装饰一下,记录我点了摩卡
    }
    public String getDescription(){
        return beverage.description +"、Mocha";
    }
    public double cost(){
        return beverage.cost()+3.33;//价钱计算在这了,拿到了要装饰的对象beverage,也就拿到了它现在多钱,再加上我摩卡的前就是总共的钱啦
    }
}
//豆浆装饰器
class Soy extends CondimentDecorator{
    Beverage beravage;
    public Soy(Beverage bevarage){
        this.beravage = bevarage;
        description = beravage.getDescription() +"、Soy";

    }
    public String getDescription(){
        return beravage.description + "、Soy";
    }
    public double cost(){
        return beravage.cost()+4.44;
    }
}
//奶泡装饰器
class Whip extends CondimentDecorator{
    Beverage beverage;
    public Whip(Beverage beverage){//相同类型、也就是相同超类,是为了保证这块参数放的进去
        this.beverage = beverage;
        description = beverage.getDescription() +"、Whip";
    }
    public String getDescription(){
        return beverage.getDescription() +"、Whip";
    }
    public double cost(){
        return beverage.cost()+5.54;
    }
}
//牛奶装饰器
class Milk extends CondimentDecorator{
    Beverage beverage ;
    public Milk(Beverage beverage ){
        this.beverage = beverage;
        description = beverage.getDescription() +"、Milk";
    }
    public String getDescription(){
        return beverage.getDescription()+"、Milk";
    }
    public double cost(){
        return beverage.cost()+9.9;
    }
}

5.现在就可以写个简单测试类啦

public  class DecoratorPattern {
    public static void main(String args[]){
        Beverage beverage= new Espresso();
        beverage = new Whip(beverage);//装饰器构造时就是决定往哪个对象添加装饰时
        beverage = new Soy(beverage);
        System.out.println("您好:你点了"+beverage.getDescription()+" 总共$"+beverage.cost());
        Beverage beverage2 = new HouseBlend();
        beverage2 = new Soy(beverage2);
        beverage2 = new Soy(beverage2);
        beverage2 = new Mocha(beverage2);
        System.out.println("您好:你点了"+beverage2.getDescription()+" 总共$"+beverage2.cost());
        Beverage b = new Mocha(new Mocha(new Whip(new DarkRoast())));
        System.out.println("您好:你点了"+b.getDescription()+" 总共$"+b.cost());
//      Beverage c = new Decaf();
//      c = new Milk(c);
//      c = new Milk(c);
//      c = new Milk(c);
        Beverage c = new Milk(new Milk(new Milk(new Decaf())));
        System.out.println("您好:你点了"+c.getDescription()+" 总共$"+c.cost());

    }
}

结果:
您好:你点了Espresso、Whip、Soy 总共$12.48
您好:你点了HouseBlend、Soy、Soy、Mocha 总共$15.51
您好:你点了DarkRoast、Whip、Mocha、Mocha 总共$18.8
您好:你点了Decaf、Milk、Milk、Milk 总共$37.4


装饰者模式:java I/O
这里写图片描述

猜你喜欢

转载自blog.csdn.net/fightingitpanda/article/details/80598683