首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

装饰器方式

2013-11-09 
装饰器模式浅谈装饰器模式 序: 今天,为了满足我们项目组长的愿望,硬非要把一个简单的一个接口实现函数,扩

装饰器模式
浅谈装饰器模式

序:
今天,为了满足我们项目组长的愿望,硬非要把一个简单的一个接口实现函数,扩展为装饰器模式进行处理。据说可以
在以后扩展的时候很有好处。于是乎,我今儿就大学了一把装饰器模式,下面我就谈谈自己的理解吧。

正文---开整:
装饰器模式,顾名思义就是给类或者接口进行装饰的模式。模式这玩意说白了就是把一些浅显易懂的东西,冠以很高深
的名词,让人摸不着头脑,有点类似于哲学。不过里面的思想不可否认还是很有道理的,不然估计也不会有那个神经病
吃多了去搞这玩意,从此让诸位欲成为编程高手的人必经的一个难关。

装饰器涉及四个名词
1、接口或者抽象基类
2、被装饰对象,也就是一个简单的实现了1中提到的接口或者抽象基类的实现类。
3、装饰对象,就是去装饰被装饰对象的对象
4、继承装饰对象类的子类,也就是具体的装饰器类了。
说了这么多,估计你基本跟没听说过一样。好了,来段代码,看看

//这是第一类名词
public interface IDecorate
{
public void sayHello();
}

//这是第二类名词
public class DecorateImpl implements IDecorate
{
public void sayHello()
{
System.out.print("Hello");
}
}

//这是第三类名词,真正的装饰器就在这里开始了,也是所有欲实现装饰器的父类
public class Decorate implements IDecorate
{
//声明一个被装饰的对象
private IDecorate decorate;

//被装饰对象从装饰器的构造函数中传进来(必须这样做)
public Decorate(IDecorate decorate)
{
this.decorate = decorate;
}

//在基类装饰器中只调用被装饰对象的方法
public void sayHello()
{
decorate.sayHello();
}
}
再对这个装饰器的基类说明一下,在每个装饰器模式中,这个类的结构基本不变
或者说这上面是装饰器第三类名词中最小的类了,必须有以上定义的这些元素。

//这是第四类名词,装饰就看这里了
public class SimpleDecorate extends Decorate
{
public Decorate(IDecorate decorate)
{
super(decorate);
}

//开装饰了哦。。。
public void sayHello()
{
//在原来的方法中加入了sayChina方法。
sayChina();

super.sayHello();

//在原来的方法中加入了sayWorld方法。
sayWorld();
}

public void sayChina()
{
System.out.print("China, ");
}

public void sayWorld()
{
System.out.print(" World!\n");
}
}

//来,测试一下
public void TestDecorate()
{
//不使用装饰器
public static void unUseDecorate(IDecorate decorate)
{
//输出 Hello
decorate.sayHello();
}

//使用装饰器
public static void useDecorate(IDecorate decorate)
{
IDecorate simpleDecorate = new SimpleDecorate(decorate);

//要调用装饰了的方法
//输出 China, Hello World!
simpleDecorate.sayHello();
}

public static void main(String[] argv)
{
IDecorate decorate = new DecorateImpl();
}
}
//是不是发现,原来只输出的hello的方法被装饰后,在其前和其后分别输出了china和world啦。

看到装饰器的威力了吧,把原来不变的方法改变了。那我们就来谈谈他的使用场景吧:
1、装饰器模式主要装饰供外部调用的接口方法,如果一个接口方法只是提供给内部调用,则不能使用该模式。
2、装饰器模式主要装饰可能要改变的接口方法,如果类中的某种行为在将来可能发生变化,而你又懒得去改变
   原来的类,那么就可以考虑使用装饰器模式了。
  
注意:模式只是解决问题的一种途径,没有必要非得在某块使用模式,所以装饰器模式这种东西,切勿刻意为之。
见识肤浅,望各位指教。



装饰模式是用于对象的创建,而此对象的创建基于原来对象的加强,也就是通过原组件对象的参数传递,把此对象层层加强。例如:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
通过层层的参数传递,把InputStream适配为InputStreamReader再装饰加强为BufferedReader。这里的参数的传递是关键,是通过引用而非继承方式。

装饰器中的继承的实质是为了类的兼容的需要,便于参数引用可以层层传递兼容,而不是通过继承实现功能的扩展,功能扩展主要在实例的引用。一般来说是纵向结构,如果只是一层继承实现,其余装饰类用横向实现的话,也是可以的,但是这个和纵向相比没有什么不同。

装饰器模式主要由两部分组成,一部分是组件,另一部分是装饰器。组件是本体,也就是初始的、最里层的参数;组件是加强件,供功能扩展时使用,顶层装饰器拥有组件的引用,装饰类可以任意组合。

其对象具有怎样的功能并不是决定于其继承结构和层次,而是在这个对象构造的时候使用到了那些类的引用,那其功能就是这些对象的总功能。
装饰器一般有一个抽象装饰器作为其顶级装饰器,包括共享的属性和方法。而抽象装饰器的所有子类从原则上来说是平等的,彼此不依赖,以便于对象构造时的功能组装。
纯净的装饰器没有扩展方法。

代码:
A a = new A();      // component
B b = new B(a);     // decorator
C c = new C(b);     // decorator: sub class of B
D d = new D(a);     // decorator: sub class of C
b具备的功能:a+b
c具备的功能:a+b+c
d具备的功能:a+d



装饰模式是在一个对象的外围创建一个称为装饰器的封装,动态地给这个对象添加一些额外的功能。以对客户端透明的方式扩展对象的功能。
装饰器中的继承的实质是为了类的兼容的需要,便于参数引用可以层层传递兼容,而不是通过继承实现功能的扩展,功能扩展主要在实例的引用。一般来说是纵向结构,如果只是一层继承实现,其余装饰类用横向实现的话,也是可以的,但是这个和纵向相比没有什么不同。

装饰器模式主要由两部分组成,一部分是组件,另一部分是装饰器。组件是本体,也就是初始的、最里层的参数;组件是加强件,供功能扩展时使用,顶层装饰器拥有组件的引用,装饰类可以任意组合。
优点:

    装饰器与继承的目的都是扩展对象的功能,但装饰器提供了比继承更大的灵活性,可以动态的决定是“粘上”还是“去掉”一个装饰。
      通过使用不同的具体装饰类和这些类的排列组合,可以创建出很多不同行为的组合。

    缺点:

    装饰器比继承关系使用更少的类,但比继承关系使用更多的对象,更多的对象会使查错变得更困难,特别是这些对象看上去很像的时候。

以蛋糕为例子,代码如下:
组件(被装饰着)Cake.java
package decorator;

public  class Cake {  
    String remark = "蛋糕";  
    public String getRemark() {  
        return remark;  
    }  


package decorator;

//抽象装饰
public abstract class Decorator extends Cake{  
    Cake cake;  
    /** 
     * 引用一个Cake. 
     * 让被装饰者进入装饰者之中。这里用的是构造方法注入。 
     * 这样就可以调用Cake实例的方法了。 
     * @param cake 
     */ 
    public Decorator(Cake cake){  
        this.cake=cake;  
    }  
    /** 
     * 让装饰器的子类都去实现getRemark方法。业务需要每个装饰器都要有描述。 
     */ 
    public abstract String getRemark();  


package decorator;

public class FlowerDecorator extends Decorator{  
   
    public FlowerDecorator(Cake cake){  
        super(cake);//调用父类的构造方法,可以获取Cake的实例了。就可以调用Cake实例的方法.  
        super.remark="一朵玫瑰花";  
    }  
       
 
    public String getRemark() {  
    return super.remark+"+"+cake.getRemark();  
    }  



package decorator;

public class ChocolateDecorator extends Decorator{
public ChocolateDecorator(Cake cake){  
        super(cake);//调用父类的构造方法,可以获取Cake的实例了。就可以调用Cake实例的方法.  
        super.remark="巧克力";  
    }

public String getRemark() {  
        return super.remark+"+"+cake.getRemark();  
    } 
}

package decorator;

public class CheeseDecorator extends Decorator{

public CheeseDecorator(Cake cake){  
        super(cake);//调用父类的构造方法,可以获取Cake的实例了。就可以调用Cake实例的方法.  
        super.remark="奶酪";  
    }

public String getRemark() {  
return super.remark+"+"+cake.getRemark();   
    } 
}

package decorator;

public class Client {
public static void main(String[] args){  
        //用果仁,花包装巧克力蛋糕。  
        Cake FlowerChocolateCheeseCake = new FlowerDecorator(new ChocolateDecorator(new CheeseDecorator(new Cake())));  
        System.out.println(FlowerChocolateCheeseCake.getRemark());  

    }  
}

热点排行