设计模式之Decorator Pattern

Declaration

首先声明, 本篇blog的内容是参考Design pattern FAQ part 4 这篇博文写的, 图片也是来自这篇博客. 部分是翻译, 加上自己的理解形成这篇博文. 希望和大家一起学习设计模式, 共同进步.

Scene for Decorator Pattern

Decorator Pattern,也就是我们通常说的装饰者模式。最初学习设计模式的时候,就感觉这个模式很强大,但是总是没有找到合适的机会用。

装饰者模式希望做的是在运行中,动态的堆叠增加一些行为,从而改变对象的行为。

比如说考虑下面这个例子,在一个hotel中出售面包套餐,其中四个重要的产品和订单情况如下:

  • Simple bread
  • bread with chicken
  • bread with drinks
  • bread with chicken and drinks

换句话说,订单的处理行为以及订单的价格是在运行中依赖产品的组合的。

Decorator Pattern

我们先看看订单接口,如下:

interface IOrder
{
string Prepare();
double CalculateCost();
}

基础类是bread,其继承了IOrder这个接口。我们希望在bread order的基础上增加新的产品,并且相应的改变整个订单的行为。

public class OrderBread : IOrder
    {
        public string Prepare()
        {
            string strPrepare="";
            strPrepare = "Bake the bread in oven\n";
            strPrepare = strPrepare + "Serve the bread";
            return strPrepare;
        }

        public double CalculateCost()
        {
            return 200.30;
        }
    }

In Action

我们希望使用decorator pattern,动态的改变bread订单。首先我们实现一个OrderDecorator类,并且在虚函数中调用house object的方法。代码如下:

abstract class OrderDecorator : IOrder
    {
        protected IOrder Order;

        public OrderDecorator(IOrder oOrder)
        {
            Order = oOrder;
        }
        public virtual string Prepare()
        {
            return Order.Prepare();
        }

        public virtual double CalculateCost()
        {
            return Order.CalculateCost();
        }
    }

上面我们已经完成了重要的一步就是创建decorator,下面我们创建动态行为对象,这些行为对象可以被动态的添加从而改变主对象的行为。

下面是chicken order的实现,该类的对象可以被添加到bread order上。

class OrderChicken : OrderDecorator
    {
        public OrderChicken(IOrder oOrder) : base(oOrder)
        {
        }

         public override string Prepare()
        {
            return base.Prepare() +  PrepareChicken(); 
        }
        private string PrepareChicken()
        {
            string strPrepare = "";
            strPrepare = "\nGrill the chicken\n";
            strPrepare = strPrepare + "Stuff in the bread";
            return strPrepare;
        }
        public override double CalculateCost()
        {
            return base.CalculateCost() + 300.12;
        }
    }

同样,我们可以实现增加drinks order类。

class OrderDrinks : OrderDecorator
    {
        public OrderDrinks(IOrder oOrder)
            : base(oOrder)
        {

        }
        public OrderDrinks()
        {
        }
public override string Prepare()
        {

            return base.Prepare() + PrepareDrinks();
        }
        private string PrepareDrinks()
        {
            string strPrepare = "";
            strPrepare = "\nTake the drink from freezer\n";
            strPrepare = strPrepare + "Serve in glass";
            return strPrepare;
        }

        public override double CalculateCost()
        {
            return base.CalculateCost() + 10.12;
        }
    }

最后我们展示一下client如何使用decorator patter动态的产生不同组合的订单。

Order = new OrderDrinks(new OrderChicken(new OrderBread()));
Order.Prepare();
Order.CalculateCost().ToString();

上面client输出的结果如下

Order 2 :- Drinks with chicken and bread
Bake the bread in oven
Serve the bread
Grill the chicken
Stuff in the bread
Take the drink from freezer
Serve in glass
510.54

Conclusion

装饰者模式和继承都是用于增加对象的功能,但是decorator patter的方式比继承更加的另外。另外由于具有不同的装饰者类,因此client可以灵活方便的设计出不同的行为组合。

微信公众号CodingRush

分享编程、算法、机器学习、数据挖掘、推荐系统、大数据计算框架等知识,欢迎扫码关注。
微信公众号CodingRush,分享编程、算法、机器学习、数据挖掘、推荐系统、大数据计算框架等知识,欢迎扫码关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值