码迷,mamicode.com
首页 > 编程语言 > 详细

设计模式之装饰者模式(JAVA)二

时间:2015-04-21 17:21:56      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

     上次简单说了一下什么是装饰者模式以及装饰者模式的一些特点,这次接着说装饰者模式的应用。

  主要参与的类或者接口

    1.component:修饰者和被修饰者共同继承的类,定义了装饰者和被装饰者需要实现的方法,可以单独的使用,也可以被修饰者包裹起来使用。

    2.concreteComponent:让修饰者为自己添加功能的对象,也就是最终被修饰的对象或者说是需要动态加上新行为的对象。

    3.Decorator:是具有特定装饰功能的类,用来修饰被装饰者,可以是抽象类也可以是接口,是所有装饰者共同实现的接口。

   二、装饰者模式实现图例

  技术分享

     这个本人画图能力有限就不自己作图了,这是从http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html截过来的一张装饰者模式实现的图例,

  途中的component给出的是interface,其实抽象类也是可以的;另外,一个被装饰者是可以被多个装饰者装饰的,因此图形最下面的ConcreteDecorator的旁边是可以再加上一个

   Decorator1来修饰ConcreteDecorator,当然Decorator1也是要继承component的。

 

  三、实例应用

  今天天气不错,我们来制作一个冰激凌,首先需要一个component,代码如下:

  

/**
 * component---装饰者和被装饰者都需要继承的类
 *
 */
public abstract class IceCream {
    
    public abstract void makeIceCream();

}

然后是一个concreteComponent,也就是被装饰者,代码如下:

public class MakeIceCream extends IceCream{

    @Override
    public void makeIceCream() {
        System.out.println("制作一个冰激凌");
    }

}

有了被装饰者,下面是装饰者,首先是Decorator,代码如下:

public abstract class DecoratIceCream extends IceCream{

    @Override
    public abstract void makeIceCream();
    
}

然后是ConcreteDecorator,当然ConcreteDecorator需要继承共同的Decorator,下面是两个ConcreteDecorator:

public class FruitIceCream extends DecoratIceCream{

    IceCream iceCream;
    
    public FruitIceCream(IceCream iceCream) {
        this.iceCream = iceCream;
    }

    @Override
    public void makeIceCream() {
        this.iceCream.makeIceCream();
        System.out.println("添加了水果");
    }

}
public class ChocolateIceCream extends DecoratIceCream{

    IceCream iceCream;
    
    public ChocolateIceCream(IceCream iceCream) {
        this.iceCream = iceCream;
    }

    @Override
    public void makeIceCream() {
        this.iceCream.makeIceCream();
        System.out.println("添加了巧克力");
        
    }

}

下来我们可以测试一下:

public static void main(String[] args) {
        System.out.println("测试装饰者模式。。。。。");
        
        /**
         * 测试被装饰者--可以单独使用
         */
        IceCream ic=new MakeIceCream();
        ic.makeIceCream();
        System.out.println("");
        
        /**
         * 只添加一个装饰者
         */
        DecoratIceCream dic=new FruitIceCream(ic);
        System.out.println("测试单个装饰者开始。。。");
        dic.makeIceCream();
        System.out.println("测试单个装饰者结束。。。");
        System.out.println("");
        /**
         * 测试添加多个装饰者
        */ 
        DecoratIceCream dic1=new ChocolateIceCream(new FruitIceCream(ic));
        System.out.println("测试多个装饰者开始。。。");
        dic1.makeIceCream();
        System.out.println("测试多个装饰者开始。。。");
        System.out.println("");
    }

运行结果如下:

技术分享

  通过结果我们可以看到,单独的component也是好使的,使用修饰者包裹着component也是好使的,并且修饰者可以不止一个。

  

  四、简化模式

  1.如果只有一个ConcreteDecorator的时候,比如说我这家工厂只生产水果冰激凌,这时候怎么搞呢?

    这个时候可以将ConcreteDecorator和Decorator进行合并,合并之后的模型图如下(图片的来源大家都懂的啊):

    技术分享

下面是测试类:

public interface Component {
    
    public void makeIceCream();

}
public class ConcreteComponent implements Component{

    public void makeIceCream() {
        System.out.println("制作一个冰激凌");
    }

}

被修饰者类是没有什么变化的,修饰者类变化也不大吧,下面上代码:

public class Decorator implements Component{

    Component component;
    
    public Decorator(Component component) {
        this.component=component;
    }

    public void makeIceCream() {
        component.makeIceCream();
        System.out.println("添加了奶油");
    }

}

本来是要生产水果冰激凌的,但是一不小心生产成奶油的,大家将就吃吧。因为只生产一种,所以Decorator就不需要其他类继承了,直接二合一即可。下面上测试代码:

public class Main {
    public static void main(String[] args) {
        
        /**
         * 测试Component
         */
        Component c=new ConcreteComponent();
        c.makeIceCream();
        System.out.println("");
        /**
         * ConcreteDecorator和Decorator合并后
         */
        Decorator d=new Decorator(c);
        d.makeIceCream();
        System.out.println("");
    }
}

运行结果:

 

技术分享

2.另一种简化模式就是只有一个Concrete Component类而没有抽象的Component接口,这时可以让Decorator继承Concrete Component。模型如下:

 

技术分享

这种其实也是很好理解的,上面说的两种都是可以生产多种产品的,比如生产冰激凌的同时还生产雪糕,但是这次我就直接上产汽水了,所以不需要

抽象的Component接口了,例子我就不再写了,其实也是很简单的。

 

  五、装饰者模式适用情形

  1.需要扩展一个类的功能,或者说给这个类附加额外的职责。

  2.给一个类附加功能的时候可以是动态的,而不是静态的,将附加的功能取消时也是动态的。

  3.给一个类附加多个功能,这些功能是通过排列组合的形式附加的,当采用继承的方式附加时需要产生大量的子类,或者说排列组合后的功能无法通过继承的方式来实现;

  

  六、优点和缺点

  1.在扩展对象的功能时比继承更加的灵活,但是在灵活性增加的同时复杂性也在增加;

  2.通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。但是装饰者会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

  3.装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加    新的公开的行为,实现“半透明”的装饰者模式。

 

  七、设计原则

  1. 多用组合,少用继承。
    利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
  2. 类应设计的对扩展开放,对修改关闭。
 
暂时就这样了,以后在应用中有新的问题再继续写吧。

 

  

 

设计模式之装饰者模式(JAVA)二

标签:

原文地址:http://www.cnblogs.com/liaidai/p/4444677.html

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