装饰器模式和 AOP 面向切片编程(设计模式与开发实践 P15)

文章目录

    • 示例
    • AOP

很多时候我们不希望一个类变得非常庞大,生来就包含很多职责。装饰器模式可以动态地给某个对象添加职责,而不会影响从这个类中派生的其他对象

为什么不用继承解决这个问题呢?如果用继承有可能会创造出数量庞大的子类,而如果把子类的属性变成装饰器,就可以灵活自由地组合了,就像天冷了要穿一件衣服等等

示例

从结构上看,Attack 方法进入了一个包装链,先执行火焰技能,再执行了闪电技能

// 定义游戏角色接口
interface ICharacter
{
    void Attack();
}

// 实现游戏角色类
class Character : ICharacter
{
    public void Attack()
    {
        Console.WriteLine("角色进行普通攻击!");
    }
}

// 装饰器基类
abstract class CharacterDecorator : ICharacter
{
    protected ICharacter character;

    public CharacterDecorator(ICharacter character)
    {
        this.character = character;
    }

    public virtual void Attack()
    {
        character.Attack();
    }
}

// 具体装饰器类:添加火焰技能
class FireDecorator : CharacterDecorator
{
    public FireDecorator(ICharacter character) : base(character)
    {
    }

    public override void Attack()
    {
        base.Attack();
        Console.WriteLine("释放火焰技能!");
    }
}

// 具体装饰器类:添加闪电技能
class LightningDecorator : CharacterDecorator
{
    public LightningDecorator(ICharacter character) : base(character)
    {
    }

    public override void Attack()
    {
        base.Attack();
        Console.WriteLine("释放闪电技能!");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建基本角色
        ICharacter character = new Character();

        // 添加火焰技能
        character = new FireDecorator(character);

        // 添加闪电技能
        character = new LightningDecorator(character);

        // 角色进行攻击
        character.Attack();

        // 输出结果:
        // 角色进行普通攻击!
        // 释放火焰技能!
        // 释放闪电技能!
    }
}

AOP

在这里我们使用了 C# 的 PostSharp 包,创建了方法切面监听

当 Attack 执行时,会引发 OnEntry 和 OnExit 生命周期

在分离业务代码和数据统计代码中, AOP 十分有效!

using PostSharp.Aspects;
using System;

// 日志记录切面
[Serializable]
public class LogAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine($"[Log] Entering {args.Method.Name}");
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.WriteLine($"[Log] Exiting {args.Method.Name}");
    }
}

// 游戏角色类
public class Character
{
    [LogAspect] // 应用日志记录切面
    public void Attack()
    {
        Console.WriteLine("Character attacking!");
    }
}

// 使用 AOP 的游戏示例
class Program
{
    static void Main(string[] args)
    {
        Character character = new Character();
        character.Attack();

        // 输出结果:
        // [Log] Entering Attack
        // Character attacking!
        // [Log] Exiting Attack
    }
}

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