跟着项目学设计模式(九) 装饰器模式

接上文,既然一个服务有多个消费者,在具体的功能实现上,会遇到许多有细微差别的地方,比如:

对商品的修改有些服务需要短信通知后台管理员,有些服务需要通过邮件+站内消息的形式通知相关用户,有些服务要求无需任何通知操作。

为了能兼容这些矛盾,我们尝试去添加相应的接口如下:

public interface IOrder  
{  
    //编辑
    bool OrderEdit(Order entity);  
    //编辑附带短信
    bool OrderEditWithSMS(Order entity);
    //编辑附带站内消息和邮件
    bool OrderEditWithMESSAGE_MAIL(Order entity);
}

一旦需求有了新的变化,比如,有的服务要求编辑商品后发送站内消息+邮件,有的服务要求发送短信+站内消息+邮件等等,就需要添加新的接口。这就好像是求解一道功能之间排列组合的问题,n个功能的结果就是n的阶乘。

我们现在选择在接口设计时就把结果一一列出,声明n的阶乘个方法。一不小心就违反了单一职责原则、接口隔离原则和开闭原则。

造成这种尴尬局面的根本原因是:除了最基本的编辑之外,其他的诸如短信、邮件、站内消息等附加功能是动态的,只有在调用时,才确定具体需要哪些附加功能。

是的,这里并不需要保证数据强一致性,什么短信、邮件、站内消息都是事件驱动模型里的东西,是异步调用的,并不会阻塞订单编辑操作,正是这些并不需要事务包裹的附加功能降低了模块的内聚。

基本思路:

方案1:不改变接口,而是创建一个包装对象,也就是装饰来包裹真实的对象,动态的扩展一个对象的功能=》装饰器模式

    public interface IOrder
    {
        bool OrderEdit(Order entity);
    }

    //基本编辑功能
    public class OrderBLL : IOrder
    {}

    //短信装饰器
    public class Order_SMSDecorator : IOrder
    {}

方案2:业务逻辑层添加一个消息接口,将这些附加功能封装起来,暴露给服务端,将消息发送放到服务端去解决。

装饰器模式

装饰者模式(Decorator Pattern),是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

    public interface IOrder
    {
        bool OrderEdit(Order entity);
    }

    //基本编辑功能
    public class OrderBLL : IOrder
    {
        bool IOrderBLL.OrderEdit(Order entity)
        {
            var val = new OrderDal().OrderEdit(entity);
            return val;
        }
    }

    //短信装饰器
    public class Order_SMSDecorator : IOrder
    {
        private IOrderBLL Order;

        public Order_SMSDecorator(IOrderBLL order)
        {
            this.Order = order;
        }

        bool IOrderBLL.OrderEdit(Order entity)
        {
            var val = Order.OrderEdit(entity);
            ///
            do 发送短信
            ///
            return val;
        }
    }

    //站内消息装饰器
    public class Order_MESSAGEDecorator : IOrder
    {
        private IOrder Order;

        public Order_MESSAGEDecorator(IOrderBLL order)
        {
            this.Order = order;
        }

        bool IOrderBLL.OrderEdit(Order entity)
        {
            var val=Order.OrderEdit(entity);
            ///
            do 发送站内消息
            ///
            return val;
        }
    }

    //邮件装饰器
    public class Order_MAILDecorator : IOrder
    {
        private IOrder Order;

        public Order_MAILDecorator(IOrder order)
        {
            this.Order = order;
        }

        bool IOrderBLL.OrderEdit(Order entity)
        {
            var val = Order.OrderEdit(entity);
            ///
            do 发送邮件
            ///
            return val;
        }
    }

我们来组合出不同的功能

    var order=new OrderBLL();
    //短信
    var order_SMS=new Order_SMSDecorator(orderBLL);
    //邮件
    var order_MAIL=new Order_MAILDecorator(orderBLL);
    //邮件+站内消息
    var order_MAIL_MESSAGE=new Order_MESSAGEDecorator(order_MAIL)

好了,在最终的服务项目中调用的时候,直接在IOC里组装成不同功能的对象就可以了,这里用的是轻量级的AutoFac,可以根据name的不同获取相应的对象:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    ......
    ......

    var order=new OrderBLL();
    //短信
    var order_SMS=new Order_SMSDecorator(orderBLL);
    //邮件
    var order_MAIL=new Order_MAILDecorator(orderBLL);
    //邮件+站内消息
    var order_MAIL_MESSAGE=new Order_MESSAGEDecorator(order_MAIL)

    builder.Register(o=>order).As<IOrder>()
            .Named<IOrder>("订单").SingleInstance();

    builder.Register(o=>order_SMS).As<IOrder>()
            .Named<IOrder>("订单+短信").SingleInstance();

    builder.Register(o=>order_MAIL_MESSAGE).As<IOrder>()
            .Named<IOrder>("订单+站内消息+邮件").SingleInstance();
    ......
    ......
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值