`

装饰模式梳理

阅读更多

现在又这么一个场景
一家饭店经营多年后,终于开出了第100家房间,但是现在面临一个问题!就是菜单的更新,如果菜单中一个菜的更改的话,那么就需要更改所有的菜单。
简单的说家店有10本菜谱,那么100家就需要更新10*100,那是一个很恐怖的数据!
那怎么办呢,这个时候就需要设计一套电子菜单了!他们雇佣


 了BigSoft公司的精英来开发这套系统!

好,项目就紧张的开始了,前期的需求调研,评估,UC的形成,架构的设计,详细设计。。。。
本来认为是一个很简单的系统,设计时碰到了一个问题!因为这家店有一道招牌菜---鸡。
这个鸡的性别可以分为 公鸡,母鸡。它们的价格是不一样的
但是这个鸡的来源又可以分为 中国产,日本产,不同产地的价格也是不一样的!

那这个菜单应该怎么设计呢。  是 鸡 ---- 中国公鸡,中国母鸡,日本公鸡,日本母鸡?


这样的话,将来又增加了来源美国鸡,若是鸡有了中性鸡呢?这些情况如何考虑?还是继续添加各种子类吗?

好吧!这个时候怎么办呢?伟大的BigSoft公司的精英们面对这点小问题当然是没问题了

就是采用了装饰模式,这里对于装饰模式的解释还是欠缺:



看代码;Chickren,就是被装饰的统一对象

package com.test.test.decoration; 

public abstract class Chickren { 
    
    String desc; 

    /* empty implement 
     * @see com.test.test.decoration.Chickren#cost() 
     */ 
    public abstract int cost(); 
    

    public String getDesc() { 
        return desc; 
    } 

    public void setDesc(String desc) { 
        this.desc = desc; 
    } 
    
} 

 

公鸡:

package com.test.test.decoration; 


public class Cock extends Chickren { 
    
    public Cock(){ 
        desc = "this is a cock,and it's price is $1.2"; 
    } 

    @Override 
    public int cost() { 
        return 12; 
    } 

    
} 

 


母鸡:

package com.test.test.decoration; 

public class Hen extends Chickren { 
    
    public Hen(){ 
        desc = "this is a hen "; 
    } 

    @Override 
    public int cost() { 
        return 10; 
    } 
    
} 

 
装饰类:

package com.test.test.decoration; 

public abstract class DecorationChickren extends Chickren{ 
     
    public abstract String getDesc(); 
    
    
}   

 

装饰者:
中国来的鸡

package com.test.test.decoration; 

/** 
* notice: 
* price is 15$ 
* desc: a hen from guangdong province which is so beautiful ,and it price is just 15$. 
* you just wait what ,come on baby ! 
* only one day, if you lost this time ,you will never forgive youself forever! 
* 
* @author inter12 
* 
*/ 
public class ChinaChickren extends DecorationChickren{ 

    private volatile Chickren chickren;  //这里声明为 volatile很关键! 
    
    public ChinaChickren(Chickren chickren){ 
        this.chickren = chickren; 
    } 
    
    @Override 
    public int cost() { 
        
        return chickren.cost() + 15; //具体的调用方式 
    } 

    @Override 
    public String getDesc() { 
        
        return chickren.getDesc() + "and it's not a hen ! also a china chickren! "; 
    } 
    
} 

 

日本来的鸡:

package com.test.test.decoration; 

/** 
* price is $10 
* desc :a chickren from japan,so delicious  
* @author inter12 
* 
*/ 
public class JapanChickren extends DecorationChickren { 
    
    public Chickren chick;  //注意,这里还是持有一个最初的父类接口,这样就可以做到随意的多级装饰 
    
    public JapanChickren(Chickren chick) { 
        
        this.chick = chick; 
    } 
    
    @Override 
    public String getDesc() { 
        
        return chick.getDesc()+"my god ,how delicious the chickren is!"; 
    } 

    public int cost() { 
        return chick.cost() + 10; 
    } 

} 

 


购买的人来了:

package com.test.test.decoration; 

public class ChickrenBuyer { 
    
    
    public static void main(String[] args) { 
        
//调用方式一 
//        Chickren chickren = new Hen(); 
//        chickren = new ChinaChickren(chickren); 
        
        //调用方式二 
        Chickren chickren = new ChinaChickren(new Hen()); 
        System.out.println("price:" + chickren.cost()); 
        System.out.println("desc:"  + chickren.getDesc()); 
        
        chickren = new JapanChickren(chickren); 
        System.out.println("price:" + chickren.cost()); 
        System.out.println("desc:"  + chickren.getDesc()); 
    } 
} 

 

是不是很熟悉的看到了java.io中的组合方式呢

这里做的不好的是 每个装饰的子类都有持有一个 Chickren对象,准确的应该是装饰类持有一个chickren对象,调用父类的构造方法
只改造了装饰者部分即可
下面的是改造版本:

package com.test.test.decoration; 

public abstract class DecorationChickren extends Chickren { 

    protected volatile Chickren chick; 

    public abstract String getDesc(); 

    public DecorationChickren(Chickren chickren) { 
        
        this.chick = chickren; 
    } 

    public Chickren getChickren() { 
        return chick; 
    } 

    public void setChickren(Chickren chickren) { 
        this.chick = chickren; 
    } 

    
} 

 

具体的装饰l;

package com.test.test.decoration; 

/** 
* notice: 
* price is 15$ 
* desc: a hen from guangdong province which is so beautiful ,and it price is just 15$. 
* you just wait what ,come on baby ! 
* only one day, if you lost this time ,you will never forgive youself forever! 
* 
* @author inter12 
* 
*/ 
public class ChinaChickren extends DecorationChickren{ 

    
    public ChinaChickren(Chickren chickren){ 
        super(chickren); 
    } 
    
    @Override 
    public int cost() { 
        
        return chick.cost() + 15; 
    } 

    @Override 
    public String getDesc() { 
        
        return chick.getDesc() + "and it's not a hen ! also a china chickren! "; 
    } 
    
} 

 

日本鸡:

package com.test.test.decoration; 

/** 
* price is $10 
* desc :a chickren from japan,so delicious  
* @author inter12 
* 
*/ 
public class JapanChickren extends DecorationChickren { 
    
    
    public JapanChickren(Chickren chick) { 
        super(chick); 
    } 
    
    @Override 
    public String getDesc() { 
        
        return chick.getDesc()+"my god ,how delicious the chickren is!"; 
    } 

    public int cost() { 
        return chick.cost() + 10; 
    } 

} 

 

总结:
1.适用于多维的系统,例如本案中就是个很经典例子。做菜,主料是鸡煲,鸡可以选择不同国家的鸡,鸡又可以采用不同的烧法,清蒸,红烧等。那么鸡和烧法就是两个维度,这样的情况下就可以猜装饰模式,在一个前提下,将不同的行为装饰上去。
2.语法结构上,一个抽象的主对象 一个抽象的装饰类,持有一个父类接口对象,所有继承装饰类的对象都必须持有父类接口引用,这样保证该继承路线的对象都能得到装饰!
3.装饰模式意味这一群装饰对象,并且反应了被装饰组件的类型。
4.装饰者会导致设计中出现许多小对象,如果过度使用,会让系统变的很复杂!
5.动态的将责任附加到对象上,是区别于继承的另一种方式!

 

分享到:
评论

相关推荐

    CC++与设计模式基础课程_讲义

    7. 装饰模式:动态地给对象添加新的职责,而不影响其他对象,增强了系统的灵活性。 8. 适配器模式:使不兼容的接口能够协同工作,通过包装原有对象,提供新的接口给客户端。 9. 桥接模式:将抽象部分与实现部分分离...

    CC++与设计模式基础课程-讲义

    结构型模式关心类和对象的组合,包括代理模式、装饰者模式、适配器模式、桥接模式、组合模式、外观模式和享元模式等。行为型模式关心类或对象怎样交互和怎样分配职责,包括模板方法模式、命令模式、责任链模式等。 ...

    C++设计模式基础教程.pdf

    7. 装饰者模式(Decorator Pattern):动态的给一个对象添加一些额外的职责。 8. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口。 9. 桥接模式(Bridge Pattern):将抽象局部与实际...

    软件秘籍--设计模式那点事随书光盘

    结构型模式如适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观模式和享元模式,关注的是如何将类和对象组合在一起,以形成更大的结构。行为型模式如策略模式、模板方法模式、观察者模式、迭代器模式、...

    JAVA设计模式整理(有部分参考代码)

    10. **装饰模式**:允许向一个现有的对象添加新的行为或责任,而无需改变其本质结构。 11. **外观模式**:为子系统提供了一个统一的接口,使得子系统更加容易使用。 12. **享元模式**:在不牺牲可扩展性的前提下,...

    java与模式 源代码

    设计模式包括创建型模式(如单例、工厂方法、抽象工厂)、结构型模式(如适配器、装饰器、代理)和行为型模式(如策略、观察者、责任链)等。 2. **Java编程语言**:Java是一种广泛使用的面向对象的编程语言,以其...

    深入浅出设计模式之附录A

    - **装饰器模式**:动态地给一个对象添加一些额外的职责。 - **代理模式**:为其他对象提供一个代理以控制对这个对象的访问。 #### 3. 行为型模式 这类模式关注于对象之间的职责分配。常见的行为型模式有: - **...

    【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

    装饰模式 外观模式 享元模式 代理模式 创建模式 抽象工厂模式 工厂方法模式 建造这模式 原型模式 单例模式 行为模式 责任链模式 命令模式 解释器模式 迭代器模式 中介者模式 备忘录模式 观察者...

    C/C++设计模式基础教程

    - **装饰者模式**:动态地给一个对象添加一些额外的职责,提供比继承更灵活的替代方案。 - **适配器模式**:允许不兼容的接口协同工作。 - **桥接模式**:将抽象部分与其实现部分分离,使得两者可以独立变化。 -...

    CC++与设计模式讲义.pdf

    7. 装饰者模式(Decorator Pattern),动态地给一个对象添加一些额外的职责。 8. 适配器模式(Adapter Pattern),将一个类的接口转换成客户希望的另外一个接口。 9. 桥接模式(Bridge Pattern),将抽象部分与实现...

    23种设计模式整理(很全).pdf.zip

    - 装饰模式(Decorator):动态地给对象添加一些额外的职责,增加功能而不改变原有结构。 - 外观模式(Facade):为子系统提供一个统一的接口,简化外部访问。 - 代理模式(Proxy):为其他对象提供一种代理以...

    24种设计模式介绍与6大设计原则

    13. 装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责。就增加功能而言,装饰模式比生成子类更为灵活。 14. 迭代器模式(Iterator Pattern):提供一种方法顺序访问一个聚合对象中的各个元素,...

    C++设计模式第一天

    1. **设计模式讲义.doc、设计模式讲义.pdf**:这些文档很可能包含了课程的主要内容,包括设计模式的基本分类,如创建型、结构型和行为型模式,以及每种类型的代表模式如单例模式、工厂模式、适配器模式、装饰器模式...

    NUAA-设计模式与软件体系结构-复习资料

    这份资料详细地介绍了设计模式和软件体系结构的相关知识,适用于需要深入了解这两个领域的读者。...整体来看,这份资料对设计模式和软件体系结构进行了系统的梳理,有助于我们更好地理解这两个领域的知识。

    各设计模式总结与对比.rar

    - 装饰模式:动态地给一个对象添加一些额外的职责,提供比继承更具弹性的替代方案。 - 外观模式:提供一个统一的接口,用来访问子系统中的一组接口。 - 代理模式:为其他对象提供一种代理以控制对这个对象的访问...

    面向对象与设计模式基础笔记

    ### 面向对象与设计模式基础知识点梳理 #### 一、面向对象的基本概念 **面向对象编程(Object-Oriented Programming, OOP)** 是一种编程范式,其核心思想是将现实世界中的事物抽象成类(Class),并通过类创建...

    高职院校Java程序设计课程中设计模式的教学设计与实施.pdf

    5. 设计模式的类别包括但不限于工厂模式、单例模式、策略模式、观察者模式、装饰模式等,这些都是程序员应当熟练掌握的模式。 6. 文档提到了UML(统一建模语言)和API(应用程序编程接口)的重要性,这两者都是软件...

Global site tag (gtag.js) - Google Analytics