`
lwbbupt
  • 浏览: 35166 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java设计模式——装饰者模式

阅读更多



一、什么情况下考虑使用“装饰者模式”?

       当我们需要将责任动态的附加到对象上的时候;也就是说,我们开发设计的对象中有某一部分的功能现在还不能确定,以后需要动态的添加或者去掉。或者是在使用继承比较困难的时候,可以采用组合的实现方式(继承与复用)。

        结合下面一个实际可能应用的场景来进行分析:



 

       此为某一咖啡店的简单的菜单系统,其中所有的咖啡必须继承自Beverage类,咖啡中需要根据顾客的要求,加入巧克力、豆浆等调料,然后依据加入的调料的不同收取相应的费用。

       eg:菜单上的StarbuzzCoffee实际为:HouseBlend + 2 * Mocha + Soy 调制而成,该如何实现呢?

如果采用装饰着模式的话可以让Mocha来装饰StarBuzzCoffee,然后Soy来装饰Mocha,在计算价格时只需要由外到内依次调用相应的价格即可。

       装饰者模式的一些概念:

       ①装饰者和被装饰者有相同的超类型

       ②你可以用一个或者多个装饰者包装一个对象。

       ③由于装饰者和被装饰对象具有相同的对象,所有在任何需要原始对象的时候,可以用装饰后的对象来替换它

       ④装饰者可以在所委托被装饰者的行为之前或者之后,加上自己的行为,以实现特定的功能。

       ⑤对象可以在任何时候被装饰,你可以在运行时选择你喜欢的装饰者来装饰对象。

二、如何实现装饰者模式?

        ①查看已有具体组件:如HouseBlend和Espresso,代码如下

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


    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

 

public class HouseBlend extends  Beverage {
    public HouseBlend(){
        description="HouseBlend";
    }

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

      ②定义抽象的装饰者(也可以不用),同时定义具体的装饰者,装饰者的目的就是增加行为到被包装的对象上,关键这在于“装饰”,所以我们采用组合让Beverage作为具体装饰者的field,同时装饰者也必须继承自Beverage,这样才可以对其进行进一步的装饰。

    

public class Mocha extends CondimentDecorator {
    protected Beverage beverage;//被包装对象

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

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

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

    ③装饰出需要的咖啡

  

public class StarbuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new HouseBlend();
        beverage = new Soy(beverage);
        beverage = new Mocha(beverage);
        beverage = new Mocha(beverage);
        System.out.println(beverage.getDescription() + " $" + beverage.cost());
    }
}

  
    java中典型使用装饰者模式的地方就是Java IO,感兴趣的话可以深入学一下。

 

ps:在编写上面的代码时发生了一个小插曲:发现最后输入的结果为:

HouseBlend ,Soy, Mocha, Mocha $1.5899999999999999

这一定不是我们想看到的结果,

这是由于float和double视为科学计算和工程计算而设计的,它们执行的为较为精确的快速近似计算,所以不能提供完全精确的结果。

所以为实现精确的计算可以使用BigDecimal

我们将其中的cost()修改如下:

 @Override
    public double cost() {
        BigDecimal cost = new BigDecimal("0.20");
        return (cost.add(new BigDecimal(Double.toString(beverage.cost()))).doubleValue());
    }

 便可以得出想要的结果了。

如果不使用BigDecimal可以将小数先转换为int或者long类型,最后在除以相应的值即可。

另外注意到了没,BigDecimal新建时使用的构造方法为为String,而没有使用double,这是为什么??

Notes:

  1. The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
  2. The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.
  3. When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.


 

 

  • 大小: 21.8 KB
  • 大小: 47.7 KB
  • 大小: 41.4 KB
1
1
分享到:
评论
2 楼 lwbbupt 2014-11-19  
LancCJ 写道
干了几年开发,我对这些竟然毫无所知,哎,我这个锤子怎么办


我也刚刚学习,现在看还不晚。
1 楼 LancCJ 2014-11-19  
干了几年开发,我对这些竟然毫无所知,哎,我这个锤子怎么办

相关推荐

    JAVA设计模式学习12——装饰器模式

    NULL 博文链接:https://alaric.iteye.com/blog/1911949

    Java设计模式-装饰者模式

    本章可以称为“给爱用继承的人一个全新的设计眼界”。我们即将再度探讨典型滥用问题。你将在本章学到如何使用对象组合的方式,做到在运行时装饰类。为什么呢?一旦你熟悉了装饰者的技巧...——《Head First 设计模式》

    Java设计模式 版本2

    对象的克隆——原型模式,复杂对象的组装与创建——建造者模式,不兼容结构的协调——适配器模式,处理多维度变化——桥接模式,树形结构的处理——组合模式,扩展系统功能——装饰模式,深入浅出外观模式,实现对象...

    java设计模式

    目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 1.3 我单纯,所以我快乐 1.4 最佳实践 ...附录:23个设计模式

    深入浅出设计模式(中文版电子版)

    4.4DecoratorPattern(装饰模式) 125 4.4.1定义 125 4.4.2现实中的装饰模式——相架 126 4.4.3C#实例——图书馆中的项目 127 4.4.4Java实例——自定义JButton 131 4.4.5优势和缺陷 133 4.4.6应用情景 134 ...

    java和设计模式ppt教程

    java和设计模式ppt包含工厂模式、建造模式、原始模型模式、单例模式、结构模式、适配器、桥梁模式、合成模式、装饰模式、门面模式、享元模式、代理模式、行为模式、解释器模式、迭代子模式、调停者模式、备忘录模式...

    深入浅出设计模式(中文版)

    4.4DecoratorPattern(装饰模式) 125 4.4.1定义 125 4.4.2现实中的装饰模式——相架 126 4.4.3C#实例——图书馆中的项目 127 4.4.4Java实例——自定义JButton 131 4.4.5优势和缺陷 133 4.4.6应用情景 134 ...

    design-pattern-java.pdf

    扩展系统功能——装饰模式(三) 扩展系统功能——装饰模式(四) 外观模式-Facade Pattern 深入浅出外观模式(一) 深入浅出外观模式(二) 深入浅出外观模式(三) 享元模式-Flyweight Pattern 实现对象的复用——...

    Pattern-Decorator-Java:设计模式工作坊——装饰者模式

    您必须实现装饰器模式,以便可以在运行时添加提到的服务。 作为开发服务如何工作的示例,在运行时创建一个用加密和缓存装饰的 JSON 策略,以及一个带有日志记录的 XML 策略。 请记住,您必须提供源代码和详细说明所...

    quanke#design-pattern-java#扩展系统功能——装饰模式(二)1

    装饰模式的核心在于抽象装饰类的设计,其典型代码如下所示://维持一个对抽象构件对象的引用public Decorator(Component component

    设计模式——开发常用的设计模式梳理

    本文来自51cto,文章主要介绍了策略模式、观察者模式、装饰模式、单例模式以及饿汉模式等的相关内容。泛化=实现>组合>聚合>关联>依赖一个人(Person)可以买车(car)和房子(House),那么就可以称:Person类依赖于Car类...

    设计模式精解 译者:熊节 程序员必看书籍之一 part2

    设计模式精解(Design Patterns Explained) ...如何实现关键模式——Strategy(策略)、Observer(观察者)、Bridge(桥接)、Decorator(装饰)等等。 共同点/变化点分析、设计模式以及它们如何帮助理解抽象类。

    java高手真经 (UML建模+设计模式+面向服务架构) 卷8

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷6

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    管理系统javasal源码-Design-Patterns-Demo:超全的设计模式——理论+实现demo

    设计模式 源码地址: 博客地址: 分类 序号 模式 & 描述 包括 1 创建型模式:这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷3

    (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/abstractfactory //11.2抽象...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷1

    (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/abstractfactory //11.2抽象...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷9

    综合实例——Bug管理系统 (3)设计模式样例(24个讲解样例程序) pattern/src/principle/liskovsubstitution//10.3.2里氏代换原则 pattern/src/creation/factorymethod //11.1工厂方法模式 pattern/src/creation/...

    设计模式Demo

    针对23种设计模式,分别写了demo并画了类图帮助理解。 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰...

Global site tag (gtag.js) - Google Analytics