设计模式(六)—— 装饰模式

一、定义:

在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

二、特点:

  • 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
  • 装饰对象包含一个真实对象的引用(reference)
  • 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
  • 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

三、情景:

在深圳吃早餐,我一般会点蛋肉肠,即鸡蛋+肉+肠粉+豆浆,其中肠粉是主食,附加料是肉、鸡蛋,饮料是豆浆
下面的情景我们考虑,主食有肠粉(4元)、米粉(3元),配料有鸡蛋(1元)、肉(1.5元)、油条(2元),饮料有豆浆(1.5元)设计类来实现该情景,打印出消费单和费用。

1、主食类(StapleFood)

public abstract class StapleFood {

    private String description = "什么都没点";

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public abstract double cost();
}

2、肠粉类(RiceNoodleRolls)

public class RiceNoodleRolls extends StapleFood{

    public RiceNoodleRolls() {
        super.setDescription("肠粉");
    }

    public double cost() {
        return 4;
    }

}

3、米粉类(RiceNoodles)

public class RiceNoodles extends  StapleFood{

    public RiceNoodles() {
        super.setDescription("RiceNoodles");
    }


    public double cost() {
        return 3;
    }
}

4、配料装饰类(CondimentDecorator1)

public abstract class CondimentDecorator1 extends StapleFood{

    @Override
    public String getDescription() {
        return super.getDescription();
    }
}

5、鸡蛋类(Egg)

public class Egg extends CondimentDecorator1{

    StapleFood food;

    public Egg(StapleFood food) {
        this.food = food;
    }

    @Override
    public String getDescription() {
        return food.getDescription()+",Egg";
    }

    public double cost() {
        return 1+food.cost();
    }

}

6、肉类(Meat)

public class Meat extends CondimentDecorator1{

    StapleFood food;

    public Meat(StapleFood food) {
        this.food = food;
    }

    @Override
    public String getDescription() {
        return food.getDescription()+",Meat";
    }

    public double cost() {
        return 1.5+food.cost();
    }

}

7、饮料装饰类(CondimentDecorator2)

public abstract class CondimentDecorator2 extends CondimentDecorator1{

    @Override
    public String getDescription() {
        return super.getDescription();
    }
}

8、豆浆类(SoybeanMilk)

public class SoybeanMilk extends CondimentDecorator2{

    CondimentDecorator1 condimentDecorator1;

    public SoybeanMilk(CondimentDecorator1 condimentDecorator1) {
        this.condimentDecorator1 = condimentDecorator1;
    }

    @Override
    public String getDescription() {
        return condimentDecorator1.getDescription()+",豆浆";
    }

    public double cost() {
        return condimentDecorator1.cost()+1.5;
    }
}

9、点餐类

public class ShenzhenRiceNoodleRolls {

    public static void main(String[] args) {

        /**
         * 点餐1:肠粉,Egg,Meat,豆浆
         */
        StapleFood food = new RiceNoodleRolls();
        CondimentDecorator1 cd1 = new Egg(food);
        cd1 = new Meat(cd1);
        CondimentDecorator2 cd2 = new SoybeanMilk(cd1);
        System.out.println(cd2.getDescription());//肠粉,Egg,Meat,豆浆
        System.out.println(cd2.cost());//8.0

        /**
         * 点餐2:米粉,Egg,豆浆
         */
        StapleFood food1 = new RiceNoodles();
        CondimentDecorator1 cd3 = new Egg(food1);
        CondimentDecorator2 cd4 = new SoybeanMilk(cd3);
        System.out.println(cd4.getDescription());//RiceNoodles,Egg,豆浆
        System.out.println(cd4.cost());//5.5
    }

}

posted @ 2016-11-19 17:38  清泉白石  阅读(217)  评论(0编辑  收藏  举报