`
lastsoul
  • 浏览: 33445 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

装饰模式

 
阅读更多
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
  适用性

    1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

    2.处理那些可以撤消的职责。

    3.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支 持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类
定义被隐藏,或类定义不能用于生成子类。
来分析下 JUnit 的使用是属于哪种情况。首先实现了比静态继承更加灵活的方式,动态
的增加功能。试想为Test 的所有实现类通过继承来增加一个功能,意味着要添加不少的功
能类似的子类,这明显是不太合适的。
而且,这就避免了高层的类具有太多的特征,比如上面提到的带有警报的抽象门类。
     透明和半透明
对于面向接口编程,应该尽量使客户程序不知道具体的类型,而应该对一个接口操作。
这样就要求装饰角色和具体装饰角色要满足Liskov 替换原则。像下面这样:
Component c = new ConcreteComponent();
Component c1 = new ConcreteDecorator(c);
JUnit 中就属于这种应用,这种方式被称为透明式。而在实际应用中,比如java.io 中往
往因为要对原有接口做太多的扩展而需要公开新的方法(这也是为了重用)。所以往往不能
对客户程序隐瞒具体的类型。这种方式称为“半透明式”。
在 java.io 中,并不是纯装饰模式的范例,它是装饰模式、适配器模式的混合使用。
其它
采用 Decorator 模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅
在他们相互连接的方式上有所不同,而不是它们的类或是它们的属性值有所不同。尽管对于
那些了解这些系统的人来说,很容易对它们进行定制,但是很难学习这些系统,排错也很困
难。这是GOF 提到的装饰模式的缺点,你能体会吗?他们所说的小对象我认为是指的具体
装饰角色。这是为一个对象动态添加功能所带来的副作用

  参与者

    1.Component
      定义一个对象接口,可以给这些对象动态地添加职责。

    2.ConcreteComponent
      定义一个对象,可以给这个对象添加一些职责。

    3.Decorator
      维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。

    4.ConcreteDecorator
      向组件添加职责。
  类图

  例子
Component定义一个对象接口,可以给这些对象动态地添加职责。

public interface Person {

    void eat();
}
ConcreteComponent 定义一个对象,可以给这个对象添加一些职责。

public class Man implements Person {

public void eat() {
System.out.println("男人在吃");
}
}
Decorator 维持一个执行Component对象的指针,并定义一个与Componect 接口一致的接口。

public abstract class Decorator implements Person {

    protected Person person;
   
    public void setPerson(Person person) {
        this.person = person;
    }
   
    public void eat() {
        person.eat();
    }
}
ConcreteDectrator 想组建添加职责

public class ManDecoratorA extends Decorator {

    public void eat() {
        super.eat();
        reEat();
        System.out.println("ManDecoratorA类");
    }

    public void reEat() {
        System.out.println("再吃一顿饭");
    }
}

public class ManDecoratorB extends Decorator {
   
    public void eat() {
        super.eat();
        System.out.println("===============");
        System.out.println("ManDecoratorB类");
    }
}
Test

public class Test {

    public static void main(String[] args) {
        Man man = new Man();
        ManDecoratorA md1 = new ManDecoratorA();
        ManDecoratorB md2 = new ManDecoratorB();
       
        md1.setPerson(man);
        md2.setPerson(md1);
        md2.eat();
    }
}
result

男人在吃
再吃一顿饭
ManDecoratorA类
===============
ManDecoratorB类
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics