7.结构型模式-装饰模式
7.1 基础知识
学习难度:3
使用频率:3
总分:6
定义
装饰模式(Decorator Pattern)动态地给一个对象添加一些额外的职责,以增加功能。相比生成子类,装饰模式更加灵活。
说人话
不改变原有对象结构,就像给一个人不断穿上不同的外套,而不必改变他的衣服。
结构图
实现步骤
- 组件接口:定义操作方法
- 具体组件类:要被装饰的原始对象,实现组件接口
- 抽象装饰类:实现组件接口,定义组件对象并在构造函数传入初始化,实现操作方法。当组件接口对象不为空时,执行组件接口对象的操作方法。
- 多个具体装饰类:继承抽象装饰类,继承抽象装饰器类构造函数,重写操作方法添加额外功能。
- 客户端:实例化具体组件作为要被装饰的原始对象,实例化不同的具体装饰器传入上一装饰对象进行装饰,一系列装饰链后调用最后一个进行装饰的具体装饰器的操作方法。
说明
装饰模式是一种灵活的设计模式,常用于需要动态地增加或修改对象的功能,而又不希望改变其类结构的情况下。
7.2 模版代码
组件接口和具体组件类
// 组件接口
interface IComponent
{
void Operation();
}
// 具体组件
class ConcreteComponent : IComponent
{
public void Operation()
{
Console.WriteLine("具体组件的操作");
}
}
抽象装饰接口和具体装饰类
// 装饰抽象类
abstract class Decorator : IComponent
{
protected IComponent component;
public Decorator(IComponent component)
{
this.component = component;
}
public virtual void Operation()
{
if (component != null)
{
component.Operation();
}
}
}
// 具体装饰类,额外的方法
class ConcreteDecoratorA : Decorator
{
public ConcreteDecoratorA(IComponent component) : base(component)
{
}
public override void Operation()
{
base.Operation();
AddAdditionalOperation();
}
public void AddAdditionalOperation()
{
Console.WriteLine("具体装饰者A的额外方法");
}
}
// 具体装饰类,添加额外的字段
class ConcreteDecoratorB : Decorator
{
private string additionalField;
public ConcreteDecoratorB(IComponent component) : base(component)
{
additionalField = "具体装饰者B的额外字段";
}
public override void Operation()
{
base.Operation();
Console.WriteLine(additionalField);
}
}
客户端
class Program
{
static void Main()
{
// 创建一个具体组件
IComponent component = new ConcreteComponent();
// 使用装饰器包装组件
IComponent decoratorA = new ConcreteDecoratorA(component);
IComponent decoratorB = new ConcreteDecoratorB(decoratorA);
// 调用装饰后的操作
decoratorB.Operation();
// 具体组件的操作
// 具体装饰者A的额外方法
// 具体装饰者B的额外字段
}
}
7.3 CSharp实践
实践需求
使用装饰模式,给孙悟空穿上凤翅紫金冠和如意金箍棒。
装饰接口和孙悟空类
// 装饰器接口
interface IDecorator
{
void Decorate();
}
// 孙悟空的默认外观,只穿着兽皮
class MonkeyKing : IDecorator
{
public void Decorate()
{
Console.WriteLine("孙悟空穿着兽皮。");
}
}
抽象装备类和具体装备类
// 装备基类
abstract class Equipment : IDecorator
{
private IDecorator monkeyKing;
public Equipment(IDecorator monkeyKing)
{
this.monkeyKing = monkeyKing;
}
public virtual void Decorate()
{
monkeyKing.Decorate();
}
}
// 具体的装饰类 - 凤翅紫金冠
class PhoenixCrown : Equipment
{
public PhoenixCrown(IDecorator monkeyKing) : base(monkeyKing) { }
public override void Decorate()
{
base.Decorate();
Console.WriteLine("孙悟空戴上凤翅紫金冠。");
}
}
// 具体的装饰类 - 如意金箍棒
class RuyiJinguBang : Equipment
{
public RuyiJinguBang(IDecorator monkeyKing) : base(monkeyKing) { }
public override void Decorate()
{
base.Decorate();
Console.WriteLine("孙悟空持有如意金箍棒。");
}
}
客户端
class Program
{
static void Main(string[] args)
{
// 创建孙悟空对象
IDecorator monkeyKing = new MonkeyKing();
// 使用装饰器装饰孙悟空
monkeyKing = new PhoenixCrown(monkeyKing); // 装上凤翅紫金冠
monkeyKing = new RuyiJinguBang(monkeyKing); // 拿上如意金箍棒
// 打印孙悟空的装饰
monkeyKing.Decorate();
// 孙悟空穿着兽皮。
// 孙悟空戴上凤翅紫金冠。
// 孙悟空持有如意金箍棒。
}
}
7.4 Unity实践
实践需求
使用装饰模式,实现生成薇恩时带上两个剑圣和阿狸这两个小伙伴。
英雄组件接口和薇恩英雄类
//英雄组件接口
public interface IHeroComponent
{
//实例化英雄方法
void InstantiateHero();
}
//薇恩主英雄
public class VnHeroConcreteComponent : IHeroComponent
{
public void InstantiateHero()
{
GameObject vn = Resources.Load<GameObject>("Lesson16_结构型模式_装饰模式/Vayne");
GameObject.Instantiate(vn, Vector3.zero, Quaternion.identity);
}
}
抽象英雄伙伴装饰类和具体英雄伙伴装饰
//英雄伙伴装饰
public abstract class HeroDecorator : IHeroComponent
{
private IHeroComponent heroComponent;
public IHeroComponent SetHeroComponent(IHeroComponent heroComponent)
{
this.heroComponent = heroComponent;
return this;
}
public virtual void InstantiateHero()
{
heroComponent?.InstantiateHero();
}
}
// 剑圣装饰伙伴
public class YiHeroConcreteDecorator : HeroDecorator
{
public override void InstantiateHero()
{
GameObject yi = Resources.Load<GameObject>("Lesson16_结构型模式_装饰模式/Yi");
GameObject.Instantiate(yi, Vector3.left, Quaternion.identity);
base.InstantiateHero();
}
}
// 阿狸装饰伙伴
public class AhriHeroConcreteDecorator : HeroDecorator
{
public override void InstantiateHero()
{
GameObject ahri = Resources.Load<GameObject>("Lesson16_结构型模式_装饰模式/Ahri");
GameObject.Instantiate(ahri, Vector3.right, Quaternion.identity);
base.InstantiateHero();
}
}
客户端
public class TestDecoratorPattern : MonoBehaviour
{
private void Start()
{
// 创建薇恩主英雄组件
IHeroComponent vnHeroConcreteComponent = new VnHeroConcreteComponent();
// 创建剑圣英雄伙伴装饰
HeroDecorator yiHeroConcreteDecorator = new YiHeroConcreteDecorator();
// 创建阿狸英雄伙伴装饰
HeroDecorator ahriHeroConcreteDecorator = new AhriHeroConcreteDecorator();
// 将剑圣英雄伙伴装饰添加到薇恩主英雄组件
vnHeroConcreteComponent = yiHeroConcreteDecorator.SetHeroComponent(vnHeroConcreteComponent);
// 将阿狸英雄伙伴装饰再次添加到组件中
vnHeroConcreteComponent = ahriHeroConcreteDecorator.SetHeroComponent(vnHeroConcreteComponent);
// 实例化带有装饰的薇恩主英雄和伙伴
vnHeroConcreteComponent.InstantiateHero();
}
}
运行结果
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com