大话设计模式—装饰模式

装饰模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

大话设计模式中程杰老师给出的定义,装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

装饰模式结构图如下:

关键代码:

1、Component 类充当抽象角色,不应该具体实现。

2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。

我们通过下面的实例来演示装饰模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。

类图如下:

//抽象Shape接口,可以给这些对象添加职责
package com.dfcDemo;

public interface Shape {
    public abstract void draw();
}
//具体形状对象,可以给这些对象添加职责
package com.dfcDemo;

public class Circle implements Shape{

    @Override
    public void draw() {

        System.out.println("shape:circle.");

    }

}
//具体形状对象,可以给这些对象添加职责
package com.dfcDemo;

public class Rectangle implements Shape{

    @Override
    public void draw() {

        System.out.println("shape:rectangle.");

    }

}
package com.dfcDemo;
/** * Shape接口的抽象装饰类 * @author lmb * */
public abstract class ShapeDecorator implements Shape{

    public Shape decoratedShape;

    //ShapeDecorator类中要向构造方法传入一个被装饰的对象
    public ShapeDecorator(Shape decoratedShape){
        this.decoratedShape = decoratedShape;
    }

    @Override
    public void draw() {
        decoratedShape.draw();      
    }

}
//Shape接口的具体装饰类,继承自抽象装饰类SHapeDecorator
package com.dfcDemo;

public class RedShapeDecorator extends ShapeDecorator{

    public RedShapeDecorator decoratedShape;

    //构造方法传入一个被装饰的Shape对象
    public RedShapeDecorator(Shape decoratedShape) {
        super(decoratedShape);
    }

   @Override
   public void draw() {
      decoratedShape.draw();//画出一个图形 
      setRedBorder(decoratedShape);//为这个图形加一个红色的边框
   }

    //Shape接口抽象装饰类的子类RedShapeDecorator特有的一个装饰Shape实现类的装饰方法
    private void setRedBorder(Shape decoratedShape){
          System.out.println("Border Color: Red");
    }

}

//测试类
package com.dfcDemo;

public class TestDecorator {

    public static void main(String[] args) {

      Shape circle = new Circle();
      Shape redCircle = new RedShapeDecorator(new Circle());
      Shape redRectangle = new RedShapeDecorator(new Rectangle());

      System.out.println("Circle with normal border");
      circle.draw();//1、画图形 

      System.out.println("\nCircle of red border");
      redCircle.draw();//1、画图形 2、加红色边框

      System.out.println("\nRectangle of red border");
      redRectangle.draw();//1、画图形 2、加红色边框

    }

}

运行结果:

Circle with normal border
shape:circle.

Circle of red border
shape:circle.
Border Color: Red

Rectangle of red border
shape:rectangle.
Border Color: Red

在该实例中装饰模式是利用setBorder()来对对象进行包装。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链中。

装饰模式是为已有的功能动态地添加更多功能的一种方式。但到底我们什么时候能用到呢?

当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责和行为,比如用红色边框装饰Circle和Rectangle,但这种做大的问题在于,他们在主类中加入了新的字段、新的方法和新的逻辑,从而增加了主类的复杂度,就像起初的那个Shape类,而这些新加入的东西仅仅是对了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要的对象,因此,当需要执行特殊行为时,客户端代码就可以在运行时根据需要有选择的、按顺序的使用装饰功能包装对象。

这样我们可以总结出:

装饰模式的优点:把类中的装饰功能从类中去掉,这样可以简化原有的类,这样就能有效的把类的核心职责和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑;简而言之,装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

装饰模式的缺点:多层装饰比较复杂。

使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。

注意事项:可代替继承

你可能感兴趣的:(设计模式,Decorator,装饰模式)