定义:
动态地给一个对象添加一些额外的职责,比生成子类更为灵活。
给对象增加职责的方式有多种,从本质上讲都是通过子类复写父类的方法来实现,Decorator模式实现了一个结构让使用者更灵活一些。
理解Decorator模式的重点在动态和灵活增加对象的功能。
从《设计模式》中给出的例子,最能体现出动态两字。用户已经生成了一个TextView对象,随着输入行数的增加,需要TextView具有Scroll滚动条功能,
来上下拖动TextView,这个过程需要为TextView对象增加新的功能。接着又想为TextView添加Border边框,这个过程需要为TextView再动态的添加Border功能,
这个过程是递归嵌套的,如果愿意的话,还可以为TextView动态的增加任意多功能。
结构:
上图与《设计模式》的结构图主要的区别:decorator抽象类有个构造函数,构造函数的参数类型是component接口。
这里我理解是Decorator模式实现动态增加对象功能的重点,但是GoF的书中没有写出来(可能我理解的不对,欢迎大家交流)。
1.component是一个接口,Operation是component接口的方法;
2.decorator抽象类实现了component接口,构造函数参数为component类型,维持一个指向component对象的指针;
3.concreteC实例化decorator抽象类,Operation方法中调用addBehavior方法,增加Operation方法的功能;
4.concreteA实现了component接口,concreteA的实例化对象是要被添加功能的对象。
举例:
public interface Screen
{
/** */
public void see();
}
TV.java
public class TV implements Screen
{
/** */
public void see()
{
System.out.println("watch tv");
}
}
Decorator.java
public abstract class Decorator implements Screen
{
Screen component;
/** */
public Decorator(Screen component)
{
this.component = component;
}
/** */
public abstract void see();
}
BrightScreen.java
public class BrightScreen extends Decorator {
public BrightScreen(Screen component) {
super(component);
// TODO Auto-generated constructor stub
}
@Override
public void see() {
// TODO Auto-generated method stub
this.network();
component.see();
}
private void network(){
System.out.print("bright ");
}
}
ThreeDScreen.java
public class ThreeDScreen extends Decorator
{
public ThreeDScreen(Screen component) {
super(component);
// TODO Auto-generated constructor stub
}
/** */
public void see()
{
this.threed();
component.see();
}
private void threed()
{
System.out.print("3d ");
}
}
Test.java
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Screen screen = new TV();
screen.see();
screen = new ThreeDScreen(screen);
screen.see();
screen = new BrightScreen(screen);
screen.see();
}
}
输出:
watch tv
3d watch tv
bright 3d watch tv
上面Test.java的代码看出如果扩展screen对象的功能,screen对象如果想扩展3d功能就screen = new ThreeDScreen(screen),如果想再扩展高亮功能就new BrightScreen(screen),这样递归下去就可以灵活的为screen对象扩展多个功能。
附件: