装饰者模式

来源:互联网 发布:男加厚棉服淘宝 编辑:程序博客网 时间:2024/06/05 10:12

七、装饰模式

    动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。(与建造者模式不同,建造者模式要求建造过程必须是稳定的(按顺序),但是装饰模式完全可以不按照特定顺序,是一种组合)。

装饰模式以对客户透明的方式动态的给一个对象附加上更多的职责。客户端并不会感觉对象在装饰前和装饰后有什么不一样。装饰模式可以在不是用创建更多子类的情况下,将对象的功能加以扩展。

7.1装饰模式中的角色:

l 抽象构件(Component):给出一个抽象接口,一规范准备接受附加责任的对象。

l 具体构件(ConcreteComponent)角色:定义一个将要接受附加责任的类。

l 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并且定义了一个与抽象构建接口一致的接口。

l 具体装饰(ConcreteDecorator)角色:负责给构件对象贴上附加责任。

//抽象构建角色(Component):

    public interface Component{

//抽象方法子类必须继承,无{}

        public void sample Operation();

}

//具体构件角色(ConcreteComponent):

publicclass ConcreteComponent implements Component{

        @override

    public void sampleOperation(){

    //书写相关代码

}

}

//装饰角色(ConcreteDecorator):

publicclass Decorator implements Component{

    private Component component;

    public Decoratortor(Component component){

        This.component=componennt;

}

@override

public void sampleOperation();

}

//具体装饰角色:

publicclass ConcreteDecoratorA extends Decorator{

    public ConcreteDecoretorA(Componentcomponent){

Super(componennt);

}

@override

public void sampleOperation(){

Super.sampleOperation();

//写相关代码

}

}

publicclass ConcreteDecoratorB extends Decorator{

    public ConcreteDecoretorBComponentcomponent){

Super(componennt);

}

@override

public void sampleOperation(){

super.sampleOperation();

//写相关代码

}

}

 

 

7.2优点:

l 把类中的装饰功能从类中版以去除,这样可以简化原有的类,有效的吧类的核心职责和装饰功能区分开来,而且可以去除相关类的重复装饰逻辑。

l 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态的君顶贴上一个需要的装饰,或者踢掉有个不需要的装饰。继承关系则不同,继承关系是静态的,他在系统运行前就决定了。

l 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

7.4缺点:

l 由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较小的类,当然设计类比较容易进行。但是另一方面,用于装饰模式会产生比继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去很像。

应用:装饰模式在java语言中的应用最著名的应用莫过于java I/O标准库的设计了。

 

7.5 例子:齐天大圣七十二变:

 孙悟空有七十二般变化,他的每一种变化都给他带来一种附加的本领。他变成鱼儿时,就可以到水里游泳;他变成鸟儿时,就可以在天上飞行。

  本例中,Component的角色便由鼎鼎大名的齐天大圣扮演;ConcreteComponent的角色属于大圣的本尊,就是猢狲本人;Decorator的角色由大圣的七十二变扮演。而ConcreteDecorator的角色便是鱼儿、鸟儿等七十二般变化。

 

 

 

 

源代码:

  抽象构件角色“齐天大圣”接口定义了一个move()方法,这是所有的具体构件类和装饰类必须实现的。//抽象方法子类必须继承,无{}

 

//大圣的尊号

public interface TheGreatestSage {

    public voidmove();

}

 // 具体构件角色“大圣本尊”猢狲类

//复制代码

public class Monkey implements TheGreatestSage {

 

    @Override

    public void move(){

        //代码

       System.out.println("Monkey Move");

    }

}

复制代码

  抽象装饰角色“七十二变”

复制代码

public class Change implements TheGreatestSage {

    privateTheGreatestSage sage;

   

    publicChange(TheGreatestSage sage){

        this.sage =sage;

    }

    @Override

    public void move(){

        // 代码

        sage.move();

    }

}

 

 

复制代码

  具体装饰角色“鱼儿”

复制代码

public class Fish extends Change {

   

    publicFish(TheGreatestSage sage) {

        super(sage);

    }

    @Override

    public void move(){

        // 代码

       System.out.println("Fish Move");

    }

}

复制代码

 

  具体装饰角色“鸟儿”

复制代码

public class Bird extends Change {

   

    publicBird(TheGreatestSage sage) {

        super(sage);

    }

 

    @Override

    public void move(){

        // 代码

       System.out.println("Bird Move");

    }

}

复制代码

  客户端类

 

复制代码

public class Client {

 

    public static voidmain(String[] args) {

       TheGreatestSage sage = new Monkey();

        // 第一种写法

       TheGreatestSage bird = new Bird(sage);

       TheGreatestSage fish = new Fish(bird);

        // 第二种写法

       //TheGreatestSage fish = new Fish(new Bird(sage));

        fish.move();

    }

 

}

复制代码

  “大圣本尊”是ConcreteComponent类,而“鸟儿”、“鱼儿”是装饰类。要装饰的是“大圣本尊”,也即“猢狲”实例。

 

  上面的例子中,系统把大圣从一只猢狲装饰成了一只鸟儿(把鸟儿的功能加到了猢狲身上),然后又把鸟儿装饰成了一条鱼儿(把鱼儿的功能加到了猢狲+鸟儿身上,得到了猢狲+鸟儿+鱼儿)。  “大圣本尊”是ConcreteComponent类,而“鸟儿”、“鱼儿”是装饰类。要装饰的是“大圣本尊”,也即“猢狲”实例。

  上面的例子中,系统把大圣从一只猢狲装饰成了一只鸟儿(把鸟儿的功能加到了猢狲身上),然后又把鸟儿装饰成了一条鱼儿(把鱼儿的功能加到了猢狲+鸟儿身上,得到了猢狲+鸟儿+鱼儿)。

8、Memento(备忘录模式)

备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。

备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

备忘录模式所涉及的角色有三个:

 Originator(发起人): 负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。

 Memento(备忘录): 负责存储Originnator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento,备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。

、 Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。

 

//发起者

Public classOriginator {

   privateString state;

       /**

        * 工厂方法,返回一个新的备忘录对象

      */

       public Memento createMemento(){

         return new Memento(state);

     }

 

      /**

       * 将发起人恢复到备忘录对象所记载的状态

     */

        public void restoreMemento(Mementomemento){

           this.state =memento.getState();

    }

 

    public String getState() {

        returnstate;

    }

 

      public void setState(Stringstate) {

          this.state = state;

      System.out.println("当前状态:"+ this.state);

    }

}

//备忘录

public classMemento {

 

private String state;

 

        public Memento(String state){

            this.state = state;

      }

    public String getState() {

       returnstate;

    }

    publicvoidsetState(String state) {

           this.state = state;

    }

  

}

 

//管理者:

public classCaretaker {

 

        private Memento memento;

      /**

       * 备忘录的取值方法

         */

      public Memento retrieveMemento(){

         return this.memento;

        }

      /**

         * 备忘录的赋值方法

       */

      public void saveMemento(Mementomemento){

          this.memento = memento;

      }

}

 

使用:

//发起人

Originator o = new Originator();

//管理者

Caretaker c = new Caretaker();

//改变负责人对象的状态

o.setState("On");

//创建备忘录对象,并将发起人对象的状态储存起来

c.saveMemento(o.createMemento());

//修改发起人的状态

o.setState("Off");

//恢复发起人对象的状态

o.restoreMemento(c.retrieveMemento());

 

 

 

0 0