装饰模式

含义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为活跃。也可以说向一个现有的对象添加新的功能,同时又不改变其结构

实现过程:

  • 理论性:创建多装饰类,用于包装现有的类,实现在保持类方法签名完整性的前提下,提供了额外的功能
  • 比喻:穿衣是对人的装饰过程,从最底层的内衣、上下衣服、饰品,每一层都是在上一层的基础上进行装饰过程,即不改变底层又添加了新功能

优缺点:

  • 优点:
    • 可以动态地扩展一个实现类的功能
    • 装饰类和被装饰类可以独立发展,而非相互耦合,即把核心功能和修饰功能拆分
  • 缺点:
    • 由于核心是多层次装饰,某一层出问题检测费时,而且需要有严格的装饰顺序

适用场景:

  • 扩展一个类的功能
  • 动态增加、删除功能

项目示例:

对人物杰克(装饰对象)进行装饰,可装饰物有:T恤、垮裤、破球鞋

// 装饰对象:
// ---------
class Person
{
    private string name;

    public Person() { }
    public Person(string name) { this.name = name; }

    public virtual void Show()
    {
        Console.WriteLine($" 装扮的{name}");
    }
}

// 抽象服饰类 Decorator:
// --------------------
class Finery : Person
{
    //打扮的对象
    protected Person component;

    //打扮
    public void Decorator(Person component) { this.component = component; }

    public override void Show()
    {
        if (component != null)
            component.Show();
    }
}

// 具体服饰类:
// ----------
class TShirts : Finery
{
    public override void Show()
    {
        Console.Write("T恤 ");
        base.Show();
    }
}
class BigTrouser : Finery
{
    public override void Show()
    {
        Console.Write("垮裤 ");
        base.Show();
    }
}
class Sneakers:Finery
{
    public override void Show()
    {
        Console.Write("破球鞋 ");
        base.Show();
    }
}

// 客户端:
// -------
class Client
{
    static void Main()
    {
        //创建装饰对象:杰克
        Person jack = new Person("杰克");

        Console.WriteLine("第一种装扮:");

        // 创建装饰物:
        // ----------
        var shirts = new TShirts();
        var sneakers = new Sneakers();
        var bigtrouser = new BigTrouser();

        // 装饰过程:
        // --------
        // 机理:B对象装饰A、C对象装饰B、D对象装饰C ..
        //      核心在于都执行了base.Show() 即Finery.Show()
        shirts.Decorator(jack);
        sneakers.Decorator(shirts);
        bigtrouser.Decorator(sneakers);

        // 打印
        bigtrouser.Show();

        /* OUT:
           第一种装扮:
           垮裤 破球鞋 T恤 装扮的杰克
        */
    }
}

UML图

参考

02-10 17:56