装饰模式

装饰模式是一种用于代替继承的技术,达到无需定义子类却可以给对象动态增加职责的效果。让对象之间的继承关系转变为关联关系。

装饰模式可以在不改变已有对象本身的功能的基础上给对象增加额外的新职责,好比日常生活中的照片,可以给照片使用相框,使之具有防潮的功能,但是这样并没有改变照片本身,这便是装饰模式。

装饰模式的结构

image.png

  • Component(抽象构件):具体构件和抽象装饰类的父类,声明了具体构件中所需的业务方法,引入该抽象层可以将未被装饰的对象和装饰后的对象统一处理。
  • SpecificComponent(具体构件):派生自抽象构件,用于定义具体的构件对象,实现了抽象构件中的方法,装饰类可以给它增加额外的职责。
  • Decorator(抽象装饰类):派生自抽象构件,用于给具体构件增加职责,通常具体职责实现在抽象装饰类的子类中。内部维护一个抽象构件对象的引用,通过这个引用可以调用装饰之前对象的方法,并通过其子类扩展该方法达到装饰的目的。
  • SpecificDecorator(具体装饰类):派生自抽象装饰类,负责给构件添加新职责。每个具体装饰类都定义了新的行为,它可以调用在抽象装饰类中的方法,也可以增加新的方法。

装饰模式的实现

  • 抽象构件
abstract class Component
{
    public abstract void Operation();
}
  • 具体构件(通常只实现基本功能,复杂功能通过装饰类扩展)
class SpecificComponent : Component
{
    public override void Operation()
    {
        //实现基本功能
    }
}
  • 抽象装饰类(核心)
class Decorator : Component
{
    private Component m_Component;

    public Decorator(Component component)
    {
        this.m_Component = component;
    }

    public override void Operation()
    {
        //调用原有业务的方法,并未真正装饰,具体装饰交给子类
        this.m_Component.Operation();
    }
}
  • 具体装饰类
class SpecificDecorator : Decorator
{
    public SpecificDecorator(Component component) : base(component) { }

    public override void Operation()
    {
        //调用原有的业务方法
        base.Operation();
        //调用新增的业务方法
        this.AddedBehavior();
    }

    //新增业务方法
    private void AddedBehavior()
    {
        //具体装饰
    }
}

示例场景

开发一个可以对字符串进行加密的数据加密模块。提供最简单的加密算法字母移动实现;提供稍微复杂的逆向输出加密;提供更为高级的求模加密。用户先使用最简单的加密算法进行加密,如果觉得还不够可以对加密后的结果进行二次加密甚至三次加密,使用装饰模式设计。

代码

abstract class EncryptionComponent
{
    public abstract void EncryptionOperation(string str);
}

class Encryption : EncryptionComponent
{
    public override void EncryptionOperation(string str)
    {
        Console.WriteLine("对字符串: {0}进行位移加密", str);
    }
}

//抽象装饰类
class ComponentDecorator : EncryptionComponent
{
    private EncryptionComponent m_Component;

    public ComponentDecorator(EncryptionComponent component)
    {
        this.m_Component = component;
    }

    public override void EncryptionOperation(string str)
    {
        this.m_Component.EncryptionOperation(str);
    }
}

//逆序加密装饰类(具体装饰类)
class ReverseDecorator : ComponentDecorator
{
    public ReverseDecorator(EncryptionComponent component) : base(component) { }

    public override void EncryptionOperation(string str)
    {
        base.EncryptionOperation(str);
        this.ReverseEncryption(str);
    }

    private void ReverseEncryption(string str)
    {
        Console.WriteLine("对字符串: {0}进行逆序加密", str);
    }
}

//求模加密装饰类(具体装饰类)
class ModDecorator : ComponentDecorator
{
    public ModDecorator(EncryptionComponent component) : base(component) { }

    public override void EncryptionOperation(string str)
    {
        base.EncryptionOperation(str);
        this.ModEncryption(str);
    }

    private void ModEncryption(string str)
    {
        Console.WriteLine("对字符串: {0}进行求模加密", str);
    }
}

不进行加密

static void Main()
{
    EncryptionComponent component = new Encryption();
    //不进行装饰
    component.EncryptionOperation("装饰模式");
    Console.ReadKey();
}

运行结果
image.png

同时使用逆序加密

static void Main()
{
    EncryptionComponent component = new Encryption();
    EncryptionComponent decorate = new ReverseDecorator(component);
    decorate.EncryptionOperation("装饰模式");
    Console.ReadKey();
}

运行结果
image.png

同时使用三种加密

static void Main()
{
    EncryptionComponent component = new Encryption();
    EncryptionComponent decorate = new ReverseDecorator(component);
    decorate = new ModDecorator(decorate);
    decorate.EncryptionOperation("装饰模式");
    Console.ReadKey();
}

运行结果
image.png

装饰模式的优点

  • 相对继承而言,扩展更加灵活。
  • 可以动态扩展对象的职责。
  • 可以对一个对象进行多次装饰,通过不同的具体装饰类以及装饰类的各自排列组合能够创造出多种不同的行为组合。
  • 具体构件类和具体装饰类可以独立变化,互不影响。

装饰模式的缺点

  • 装饰模式设计会导致系统中出现很多小对象,占用更多的系统资源,影响程序性能。
  • 相对继承更加灵活却也更加复杂容易出错,对于多次装修的对象,调试时可能需要逐级定位错误,较为繁琐。

应用场景

  • 在不影响其它对象的情况下需要动态的给单个对象添加职责。
  • 不能采用继承的方式对系统进行扩展或者采用继承不利于系统的扩展和维护时可以使用装饰模式。

DoubleJ
7 声望3 粉丝

« 上一篇
组合模式