码迷,mamicode.com
首页 > 其他好文 > 详细

【设计模式】HeadFirst设计模式(三):装饰者(Decorator)模式

时间:2015-05-05 00:03:45      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:设计模式   decorator   装饰者   java   

今天就来写一下装饰者模式,该软考了,也该实习了,感觉心态静不下来,设计模式都是一些简单的小例子,但是看了这么久连简单的了解还没有完全搞定,深感惭愧,还是要安静下来,书中才有颜如玉~ ~ ~不扯了,下边进入正题

一、装饰者模式定义

在不修改原类的基础上,动态地扩展原来的对象的功能,装饰者提供了比继承更有弹性的替代方案:通过创建一个包装对象(装饰对象),来包裹真实的对象

二、装饰者模式的特点

(1) 装饰者和被装饰者有相同的超类型
(2) 可以用一个或者多个装饰者包装一个对象
(3) 因为装饰者和被装饰者有相同超类型,则可以在任何需要原始对象(被包装的对象)的场合,用装饰过的对象代替它
(4) 装饰者可以在所委托被装饰者的行为**之前与/或之后**,加上自己的行为,以达到特定的目的(注意加粗部分)
(5) 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用某装饰者来装饰对象

看到这里可能很迷惑,可以跳过看后边的具体例子然后再回头看这里就会明白了

三、 装饰者模式具体实现——设计咖啡店的订单系统

*1、首先看下咖啡店原本的类设计:*
![原本类设计](http://img.blog.csdn.net/20150504224243296)
Beverage类(抽象类):属性description由子类设置
每个子类实现cost抽象方法,返回各自价格

当然,在购买咖啡的时候,可以要求在其中加入各种调料:豆浆(Soy)、摩卡(Mocha)、奶泡(Whip)等等,咖啡店会根据加入调料收取不同的费用,所以订单系统需要考虑这些调料部分
解决方法(1):所以我们可以这样做,设计出这些类:
摩卡和奶泡深焙咖啡类、摩卡深焙咖啡类、豆浆浓缩咖啡类等等
可以看出来,我们根据调料和咖啡的种类要用排列组合计算到底需要多少类了。这简直就是”类爆炸“,制造了维护的噩梦
解决方法(2):重新设计Beverage(饮料)类如下
技术分享
重新设计后的Beverage不再是一个抽象类而是一个具体类:

public class Beverage {
    String description;
    boolean milk;
    boolean soy;
    boolean mocha;
    boolean whip;
    double milkCost = 1.0;
    double soyCost = 2.0;
    double mochaCost = 3.0;
    double whipCost = 4.0;
    //获得描述
    public String getDescription(){
        return description;
    }
    //得到调料价格
    public double cost(){
        double condimentCost = 0.0;
        if(isMilk()){
            condimentCost += milkCost;
        }
        if(isMocha()){
            condimentCost += mochaCost;
        }
        if(isSoy()){
            condimentCost += soyCost;
        }
        if(isWhip()){
            condimentCost += whipCost;
        }
        return condimentCost;
    }

    //省略milk、mocha、soy、whip的setter和getter方法
}

然后,实现DarkRoast(深焙咖啡类):

public class DarkRoast extends Beverage {
    public DarkRoast(){
        description = "我是深焙咖啡";
    }
    public double cost(){
        return 1.99+super.cost();
    }
}

然后我们写一个main函数:

public class Main {
    public static void main(String[] args) {
        //我想要一个加奶的深焙咖啡
        T t = new T1();
        t.setMilk(true);
        System.out.println("加奶的深焙咖啡价格:"+t.cost());
    }
}

打印出来结果:加奶的深焙咖啡价格:2.99
如此,我们就可以实现我们想要的了。但是,这里有一个很严重的问题:如果我们需要增加一个配料的话,我们就需要继续修改这个Beverage类了,这违反了”扩展开放,修改关闭的开—闭设计原则“。我们如何改良?
2、利用装饰者模式对系统进行重新构造
(1) 如果顾客想要摩卡和奶泡深焙咖啡,那么我们需要做的是
① 拿一个深焙咖啡对象
② 以摩卡对象装饰它
③ 以奶泡对象装饰它
④ 调用cost方法,并依赖委托将调料的价格加上去
步骤:
技术分享
等到算钱的时候只需要调用最外层Whip的cost方法就可以办到
(2) 定义装饰者模式
技术分享
3、使用装饰者模式实现咖啡店的订单系统:
技术分享
Beverage.java

public abstract class Beverage {
    protected String description = "Unknown Beverage";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

HouseBlend.java

//浓缩咖啡
public class HouseBlend extends Beverage {

    public HouseBlend() {
        description = "House Blend Coffee";
    }

    public double cost() {
        return .89;
    }
}

DarkRoast.java

//深焙咖啡
public class DarkRoast extends Beverage {

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

    public double cost() {
        return .99;
    }
}

Epresso.java

//浓缩咖啡
public class Espresso extends Beverage {

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

    public double cost() {
        return 1.99;
    }
}

CondimentDecorator.java

//配料类的超类
public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}

Mocha.java

//摩卡(配料)
public class Mocha extends CondimentDecorator {
    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

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

    public double cost() {
        return .20 + beverage.cost();
    }
}

Soy.java

//豆浆(配料)
public class Soy extends CondimentDecorator {
    Beverage beverage;

    public Soy(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ", Soy";
    }

    public double cost() {
        return .15 + beverage.cost();
    }
}

Whip.java

//奶泡(配料)
public class Whip extends CondimentDecorator {
    Beverage beverage;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ", Whip";
    }

    public double cost() {
        return .10 + beverage.cost();
    }
}

然后写一个简单的main函数:

public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());

        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        System.out
                .println(beverage2.getDescription() + " $" + beverage2.cost());

        Beverage beverage3 = new HouseBlend();
        beverage3 = new Soy(beverage2);
        beverage3 = new Mocha(beverage2);
        beverage3 = new Whip(beverage2);
        System.out
                .println(beverage3.getDescription() + " $" + beverage3.cost());
    }

【设计模式】HeadFirst设计模式(三):装饰者(Decorator)模式

标签:设计模式   decorator   装饰者   java   

原文地址:http://blog.csdn.net/u010800530/article/details/45489137

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!