大话设计模式 | 4. 装饰模式

发布于: 2020 年 07 月 12 日
大话设计模式 | 4. 装饰模式

大话设计模式 》是作者「程杰」通过趣味的场景设置,以诙谐的表达来解读和剖析「面向对象」编程思维和「设计模式」。书中的示例代码是以 .NET 的 C# 语言编写而成。

本文是我对《大话设计模式》的学习系列笔记的第四篇,装饰模式。

定义

装饰模式 (Decorator Pattern),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。可以以对客户透明的方式动态的给一个对象附上更多的责任。

给一个类或者对象增加行为有两种方式:

  1. 继承机制,通过继承一个现有类可以使得子类在拥有自身方法的同时也能拥有父类的方法。但是,这种方法是静态的,用户不能控制增加行为的方式和时机。

  2. 关联机制,将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为,以便扩展自己的行为。我们称这个嵌入的对象为装饰模式。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。

组成

装饰模式主要是由四个角色组成:

  • 抽象构件(Component)角色,是定义一个对象的接口,可以给这些对象动态地添加职责。

  • 具体构件(ConcreteComponent)角色,定义了一个具体的对象,可以给这个对象添加一些职责。

  • 抽象装饰类(Decorator)角色,继承了Component,从外类来扩展抽象构件,并定义一个与抽象构件接口一致的接口。

  • 具体装饰类(ConcreteDecorator)角色,具体的装饰对象,给构件对象添加职责。

优点

装饰模式是为已有功能动态的添加更多功能的一种方式。

当系统需要新功能时,是向旧的类中添加新代码,这些新加的代码通常装饰类原有类的核心职责或主要行为。这样,在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度。但这些新加入的东西仅仅是为了满足一些只在特定情况下才会执行的特殊行为的需要。

装饰模式能提供一个较好的解决方案,把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择性地、按顺序地使用装饰功能包装对象了。

其优点是能把类中的装饰功能从类中搬移去除,以简化原有类,有效地把类的核心职责和装饰功能区分开来。

实例

《大话设计模式》中,是通过一个人的穿衣搭配为例进行说明的。这里要考虑穿衣的类型和顺序。

创建具体构件类

由于这里只包含一个人,即一个ConcreteComponent,这里就可以直接用装饰类来继承ConcreteComponent。

public class Person
{
public Person()
{
}
private string name;
public Person(string name)
{
this.name = name;
}
public virtual void Show()
{
Console.WriteLine("Dressed {0}", name);
}
}

创建装饰类

继承构件类并来扩展构件。

abstract class Dresses : Person
{
protected Person component;
public void Decorate(Person component)
{
this.component = component;
}
public override void Show()
{
if (component != null)
{
component.Show();
}
}
}

定义具体的装饰类

在具体的装饰类中只需要运行原构件的操作。

class TShirts : Dresses
{
public override void Show()
{
Console.Write("T Shirt, ");
base.Show();
}
}
class Trousers : Dresses
{
public override void Show()
{
Console.Write("Trousers, ");
base.Show();
}
}

客户端

在主函数中(客户端),首先实例化person对象,然后用实例化的具体装饰类按顺序分别来对person进行装饰。

class Program
{
static void Main(string[] args)
{
Person person1 = new Person("person_name");
TShirts tshirt = new TShirts();
Trousers trouser = new Trousers();
tshirt.Decorate(person1);
trouser.Decorate(tshirt);
trouser.Show();
Console.WriteLine("Hello World!");
}
}

参考

本文参考了这篇文章:

发布于: 2020 年 07 月 12 日 阅读数: 5
用户头像

Puran

关注

GIS从业者,正在往开发的路上小跑。 2018.03.29 加入

从业4年的GIS开发小白,work@esri。

评论

发布
暂无评论
大话设计模式 | 4. 装饰模式