本文由码农网 – 鲁阿皓原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划

前情提要:http://blog.csdn.net/baidu_30889437/article/details/50917814

JVM:”上次给我招的工人不错啊!”

oo程序员:”………..”

JVM:”现在来我开的博物馆生意越来越好了,原来”舞台剧”的方式已经不能满足顾客的需求了”

oo程序员:”………..”

JVM:”我决定要换一种运营模式,把每个演播厅都租出去,让那些想表演节目的对象们来租演播厅和相关器械,这样我就能坐地收钱了!”

oo程序员:”………..”

JVM:”合伙干吧?怎么样?你三我七!”

oo程序员:”………..”

JVM:”四六?”

oo程序员:”成交!先说说需求。”

JVM:”首先有不同类型的演播厅和不同的装饰品/器械,每种物品都要付一定的租金,你要做的就是一件事,把总租金(演播厅+饰品/器械)算出来。”

oo程序员:”把价格表给我!”

卡通演播厅(CartoonStudio)     100

小丑演播厅(JokerStudio) 150

超级演播厅(SuperStudio) 300

气球(Balloon)                 10

灯光(Lamplight) 25

麦克风(Microphone) 20

最后还写下了这个:

public abstract class Anything_ex()
{
   String description=" ";
   public String getDescription()
   {
      return description;
   }
   public abstract int cost();
}

仔细一想也对,无论是演播厅还是装饰品,都需要描述(description)和cost(价格),写一个共同的父类无可厚非。

接着写下你设计的第一个类:

class CartoonandBalloon extends Anything_ex
{
   ....
   public int cost()
   {
      return 100+10;
   }
}   //带气球的卡通演播厅

第二个:

class CartoonandLamplight extends Anything_ex
{
   ...
   public int cost()
   {
      return 100+25;
   }
}  //带灯光的卡通演播厅

第三个:
。。。。。

没有第三个了!这样写下去可是无穷无尽的!没办法,换个思路。

在演播厅里,无论什么装饰品都有可能出现,可以把演播厅+饰品看成一个整体,通过饰品相应的has和set来控制饰品,这样的话,设计出来的类如下:

class CartoonStudio extends Anything_ex
{
    private  boolean Balloon=false;
    .... //省略其他变量,这里只以气球为例
    public boolean hasBalloon()
    {
        return Ballon;
    }
    public void setBallon()
    {
        Balloon=true;
    }
    .......//省略其他has/set方法
    public int cost()
    {
        int cost=100; //卡通演播厅的初始价格为100
        if(hasBalloon)
        {
            cost+=10;
        }
        else if(hasXXX).....//省略类推下来的代码

        return cost;
    }

}

这个看起来好多了,不用写大爆炸数量的类,虽然类写起来又臭(无数的has/set)又长(的确很长)。。。。。

但是有没有更好的方案?

答案当然是有的,不过我们必须先明确一下,上述设计的缺点。

  • 1.臭
  • 2.长
  • 3.当饰品的租金改变的时候,必须修改所有演播厅的代码(cost部分),我们当然不想这样,我们想尽可能的少修改代码(松耦合)。
  • 4.没有面对超类/接口编程。
  • 5.没有将变化的部分独立开。
  • 6.组合可能是更好的解决方案。

下面让我们看看。装饰者模式是如何解决上面问题的。

装饰者模式:动态的将责任加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

首先,我们先将演播厅和他的装饰者们分开,让装饰者继承另一个类:

public abstract class Decorater_ex extends Anyting_ex
{
      public abstract String getDescription();
}

让装饰者子类重新实现getDescription()即可。

现在我们的思路是:用装饰者装饰演播厅,例如,一个带麦克风和气球的卡通演播厅,就先让气球装饰卡通演播厅,再让麦克风装饰“带气球的卡通演播厅”

先让我们分别实现这3个类:

卡通演播厅:

class CortoonStudio extends Anything_ex
{
    public CortoonStudio()
    {
        description="CortonStudio";
    }
    publuc int cost()
    {
        return 100;
    }
}

麦克风:

class Microphone extends Decorater_ex
{
    private Anything_ex studio;
    public Microphone(Anything_ex studio )
    {
        this.studio=studio;
    }
    public String getDescription()
    {
        return studio.getDescription()+",Microphone";
    }
    public int cost()
    {
        return studio.cost()+20;
    }
}

气球:

class Balloon extends Decorater_ex
{
    private Anything_ex studio;
    public Balloon(Anything_ex studio )
    {
        this.studio=studio;
    }
    public String getDescription()
    {
        return studio.getDescription()+",Balloon";
    }
    public int cost()
    {
        return studio.cost()+10 ;
    }
}

代码:

Anything_ex CortoonStudio =new CortoonStudio();    //一个卡通演播厅对象
CortoonStudio=new Microphone(CortoonStudio); //拿麦克风装饰
CortoonStudio=new Balloon(CortoonStudio);  //拿气球装饰
System.out.println(CortoonStudio.getDescription()+"="+CortoonStudio.cost());

输出结果:

CortonStudio,Microphone,Balloon=130

结果是正确的。

这样写很好的解决了上面的问题。

  • 1.运用组合进行扩展,使当价格改变的时候,只需要修改本身的代码。
  • 2.面对超类/接口编程,使饰品增加种类的时候,并不需要修改被装饰者的代码。
  • 3.开放——关闭原则 :代码应该对扩展开放,对修改关闭。

缺陷:

  • 1.子类繁多,影响理解代码(java I/O就是装饰者模式哦。。。)。
  • 2.无法应用于需要具体类的场景。

这篇文章到此差不多结束了,作者功力尚浅,文章如有不正之处请读者指出,海涵。

Java设计模式之装饰模式趣谈的更多相关文章

  1. java设计模式学习笔记--浅谈设计模式

    设计模式的目的 编写软件的过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战.设计模式为了让程序具有更好的 1.代码重用性(即:相同功能的代码,不用多次编写) ...

  2. java设计模式之装饰模式

    发现设计模式的学习越来越让自己学习的东西太少了,应该多接触一些东西,多出去走一走. 装饰模式概念: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活(大话设计模式) 在不 ...

  3. Java——设计模式(装饰模式_IO)

     /* * 装饰设计模式: *  对一组对象的功能进行增强时,就可以使用该模式进行问题的解决; * 装饰和继承都能实现一样的特点:  就是进行功能的扩转增强. * */ public class  ...

  4. JAVA设计模式:装饰模式

    前面我们学习了代理模式: 代理模式主要使用了java的多态,干活的是被代理类,代理类主要是接活,你让我干活,好,我交给幕后的类去干,你满意就成,那怎么知道被代理类能不能干呢?同根就成,大家知根知底,你 ...

  5. java设计模式(装饰模式)

    装饰模式实现了可以动态地为原对象扩展方法 装饰对象与被装饰的都实现了同一个接口(或抽象类) 举个例子: 工作 可以边吃东西边工作,也可以边喝东西边工作,还可以工作的时候边吃边喝 创建共同接口 Work ...

  6. Java设计模式(7)装饰模式(Decorator模式)

    Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...

  7. Java设计模式学习记录-装饰模式

    前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...

  8. Java设计模式(十三) 别人再问你设计模式,叫他看这篇文章

    原创文章,转载请务注明出处 OOP三大基本特性 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类操作,对不可信的进行信息隐藏. 继承 继承是指这样一种能力,它可以使 ...

  9. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

随机推荐

  1. Cron运行原理

    from:http://blog.chinaunix.net/uid-20682147-id-4977039.html 目录 目录 1 1. 前言 1 2. 示例 1 3. 工作过程 2 4. 一个诡 ...

  2. Cocos2d-x课程大纲/学习路线

    Cocos2d-x课程大纲/学习路线 这是什么? 这个一个Cocos2d-x技术路线的课程大纲/学习大纲. 你能用它做什么? 如果你是找工作的人, 利用本大纲, 你可以学习Cocos2d-x, 做一个 ...

  3. 用javascript操作xml(三)关于Jquery的html()不兼容IE的解决办法

    当 $("#xxx").html(data); 不兼容,方法替换为 document.getElementById("xxx").innerHTML=data;

  4. Poco之ftp目录切换与创建

    TEMPLATE = app QT += qml quick widgets#LIBS += -lPocoFoundation -lPocoXML -lPocoNetSOURCES += main.c ...

  5. WPF界面特殊字符处理

          界面XAML不支持< .>.&."等字符. 使用字符实体编码进行替代,以下是pro WPF 4.5的摘要表 Special Character        ...

  6. cocos2d-x笔记4: TextField不能删除内容,以及我的解决办法。。。

    3.0正式版,win32下,TextField按下backspace键不能删除内容.网上搜了下,很早就有的问题了,正式版了竟然还不解决... 真心无力吐槽啊!!!这种巨大而又明显的Bug... 从昨天 ...

  7. KMP模板与讲解

    读书笔记终于写完了,写一下我对KMP的理解. KMP的思想就是尽量利用已经得到的信息,来降低时间复杂度,已经得到的信息存放在next数组里.算法确实很难理解,所以很难讲解..举个例子来说吧. 设字符串 ...

  8. 【Python网络爬虫三】 爬去网页新闻

    学弟又一个自然语言处理的项目,需要在网上爬一些文章,然后进行分词,刚好牛客这周的是从一个html中找到正文,就实践了一下.写了一个爬门户网站新闻的程序 需求: 从门户网站爬取新闻,将新闻标题,作者,时 ...

  9. Python的数字类型及其技巧

    Python中的数字类型 int float fractions.Fraction decimal.Decimal 数字的舍与入 int(f):舍去小数部分,只保留整数部分,所以int(-3.8)的结 ...

  10. DM8168 解码显示模块代码阅读分析

    解码/显示概述:从共享文件夹获取H264流,对264流进行解析,生成hdr文件,hdr文件中包含每一帧的信息,将视频帧信息存放在A8核分配的共享内存空间,供其他核或其他的link调用,M3 Video ...