设计模式:装饰者模式

装饰者模式动态地将责任附加到对象上。若要拓展功能,装饰者提供了比继承更有弹性的替代方案。

1. 角色

  • 抽象构件(Component)角色:要包装的原始对象,是一个抽象类或接口。
  • 具体构件(ConcreteComponent)角色:最终要装饰的实际对象,是Component的实现类。
  • 装饰(Decorator)角色:是一个抽象类,继承自Component,同时持有一个对Component实例对象的引用。
  • 具体装饰(ConcreteComponent)角色:具体的装饰者对象,是Decorator的实现类,负责给ConcreteComponent附加责任。

2. Demo背景

  • 一个奶茶店每款奶茶可以自己选添加一些辅料如燕麦,布丁,红豆,珍珠等等。添加辅料不同可能价格也不同,又或者是我们全都要,同时添加多种辅料,这样我们设计对象时就遇到了困难,难道要排列组合去创建子类吗?这样做显然是不好的,类数量爆炸,设计死板。在这时候我们就可以引用装饰者模式,用组合的方式代替继承。

3. 代码实现

  • 抽象构件类(Component):MilkyTea
public abstract class MilkyTea(奶茶)
    {
        public string description;
        public abstract double GetFee();
        //与java不一样,java父类方法不需要加关键词Virtual就可以在子类中重写
        public virtual string GetDescription()
        {
            return description;
        }
    }
  • 具体构建类(ConcreteComponent):MilkGreenTea(奶绿)
public class MilkGreenTea : MilkyTea
    {
        public MilkGreenTea()
        {
            description = "Milk Green Tea";
        }
        public override double GetFee()
        {
            return 10;
        }
    }
  • 装饰类(Decorator):CondimentDecorator(辅料)
public abstract class CondimentDecorator : MilkyTea
    {
        public MilkyTea milkyTea;
    }
  • 具体装饰(ConcreteComponent):Oats(燕麦),Pudding(布丁)
    public class Oats : CondimentDecorator
    {
        public Oats(MilkyTea milkyTea)
        {
            this.milkyTea = milkyTea;
        }
        public override double GetFee()
        {
            return 1 + milkyTea.GetFee();
        }
        public override string GetDescription()
        {
            return milkyTea.GetDescription() + ",Oats";
        }
    }
    public class Pudding : CondimentDecorator
    {
        public Pudding(MilkyTea milkyTea)
        {
            this.milkyTea = milkyTea;
        }
        public override double GetFee()
        {
            return 3 + milkyTea.GetFee();
        }
        public override string GetDescription()
        {
            return milkyTea.GetDescription() + ",Pudding";
        }
    }
  • 测试代码与运行结果
static void Main(string[] args)
        {
            MilkyTea tea = new MilkGreenTea();
            Console.WriteLine($"{tea.GetDescription()}:¥{tea.GetFee()}。");
            tea = new Pudding(tea);
            Console.WriteLine($"{((Pudding)tea).GetDescription()}:¥{tea.GetFee()}。");
            tea = new Oats(tea);
            Console.WriteLine($"{tea.GetDescription()}:¥{tea.GetFee()}。");
        }

运行结果

4. 优缺点

  • 优点:为设计注入弹性。满足开闭原则,方便拓展。
  • 缺点: 在设计中会加入大量小类。

5. 源码地址

https://github.com/DonyGu/DesignPatterns

转载于:https://www.cnblogs.com/donyblog/p/11392037.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值