装饰器模式

首先我们有一个抽象类(Animal),有三个属性,和一个发声方法,如下

/// <summary>
/// 动物抽象类
/// </summary>
public abstract class Animal
{
    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 腿的数量
    /// </summary>
    public int FootNum { get; set; }
    /// <summary>
    /// 有无尾巴
    /// </summary>
    public bool HaveTail { get; set; }


    /// <summary>
    /// 发声
    /// </summary>
    public abstract void Sound();
}

然后我们实现两个具体动物猫Cat和鸭Duck

public class Cat : Animal
{
    public override void Sound()
    {
        Console.WriteLine("喵喵喵");
    }
}

public class Duck : Animal
{
    public override void Sound()
    {
        Console.WriteLine("嘎嘎嘎");
    }
}

现在我们有需求,在动物发声前,我们需要打印时间戳,而且不要修改这两个业务类。我们通过代理模式可以实现,但是通过无论是继承还是组合的方式,都有各自缺点。而装饰器模式就结合它们的优点。
现在我们新建一个时间戳装饰器

/// <summary>
/// 时间戳装饰类
/// </summary>
public class TimeStampDecorator : Animal    //这里使用继承
{
    #region 这里使用组合
    private readonly Animal animal = null;
    /// <summary>
    /// 构造方法,传入一个Animal类
    /// </summary>
    /// <param name="_animal"></param>
    public TimeStampDecorator(Animal _animal)
    {
        animal = _animal;
    }
    #endregion


    /// <summary>
    /// 重写发声方法
    /// </summary>
    public override void Sound()
    {
        //在发声之前
        Console.WriteLine($"时间戳:{DateTime.Now}");

        //调用原来(即传入Anima)的发声方法
        animal.Sound();
    }
}
第一步:我们实现一个猫,然后发声
static void Main(string[] args)
{
    //首先实现一个具体的猫
    Animal cat = new Cat
    {
        FootNum = 4,
        HaveTail = true,
        Name = "猫"
    };

    //发声
    cat.Sound();


    Console.Read();
}

结果肯定如下
在这里插入图片描述

第二步:实现一个TimeStampDecorator类

新建一个TimeStampDecorator实例,构造函数需要一个Animal对象,我们把上面的cat传入

//首先实现一个具体的猫
Animal cat = new Cat
{
    FootNum = 4,
    HaveTail = true,
    Name = "猫"
};

//新建一个TimeStampDecorator实例,构造函数需要一个Animal对象,我们把上面的cat传入
TimeStampDecorator animal = new TimeStampDecorator(cat);
第三步:用父类Animal表示animal对象

因为TimeStampDecorator是继承自Animal,所以我们可以用Animal来表示animal对象

//首先实现一个具体的猫
Animal cat = new Cat
{
    FootNum = 4,
    HaveTail = true,
    Name = "猫"
};

//新建一个TimeStampDecorator实例,构造函数需要一个Animal对象,我们把上面的cat传入
//1. TimeStampDecorator animal = new TimeStampDecorator(cat);
Animal animal = new TimeStampDecorator(cat);
第四步:相同类用cat代替animal

上面我们对于cat实例和animal实例 都是Animal类,就像我们如下定义了一样

Animal cat = new Animal();
Animal animal= new Animal();

我们知道上诉情况,我可以使用cat=animal,所以对于第四步中,我们可以这样写

//首先实现一个具体的猫
Animal cat = new Cat
{
    FootNum = 4,
    HaveTail = true,
    Name = "猫"
};

//新建一个TimeStampDecorator实例,构造函数需要一个Animal对象,我们把上面的cat传入
//1. TimeStampDecorator animal = new TimeStampDecorator(cat);
//2. Animal animal = new TimeStampDecorator(cat);
cat = new TimeStampDecorator(cat);

我们再让cat发声
在这里插入图片描述
结果是显然的,我们在不修改Cat类的前提下,修改了CatSound()方法,而且这里把Cat换成Duck效果也是完全相同的。
当然,我们还可以套用多个装饰器,下面是一个日志装饰器,在发声后写一个日志。

public class LogDecorator : Animal
{
    private readonly Animal animal = null;
    public LogDecorator(Animal _animal)
    {
        animal = _animal;
    }

    public override void Sound()
    {
        animal.Sound();
        //发声后,我们写入日志
        Console.WriteLine("成功写入了日志");
    }
}

我们测试一下

static void Main(string[] args)
{
    //首先实现一个具体的猫
    Animal duck = new Duck
    {
        FootNum = 2,
        HaveTail = true,
        Name = "鸭子"
    };

    //装饰一个时间戳
    duck = new TimeStampDecorator(duck);
    //再装饰一个日志
    duck = new LogDecorator(duck);

    duck.Sound();

    Console.Read();
}

结果是可预料的
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值