2018年12月22日 16:47
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

现在出去面试,别人一问就是你知道多少种设计模式,知道面向对象的设计原则吗?往往有些同志就死在这些节点上,与好工作失之交臂。今天我们看一下装饰模式,这个模式可以应用于什么场景,比如你有个之前的核心业务,我们不敢轻举妄动。但是老大说要修改某个业务逻辑。比如会员管理系统中的消费扣费,因为扣费这个业务牵涉到扣当事人费用,给介绍人提成,记录消费明细,发短信给当时人等一系列核心业务流程。此时老板说我们要加一个消费层次统计,把消费100元以下,100-300,300-500元,500以上的数据记录下来,便于后续统计本店消费层次人群比例。这个时候就需要在扣费的时候根据消费金额把数据统计起来。

消费区间100100-300300-500500-10000
次数126
36959863

这个时候,我们面对这样一个需求,不敢动核心部分的代码。那么就用装饰模式实现一下,装饰下,装饰的功能更丰富。

今天我就以一个魔兽争霸的小例子来阐述以下这个模式。一个英雄接口,有放技能方法。然后有个剑圣,集成了英雄并实现英雄的放技能。

现在我们要在放技能的时候给剑圣吃一个血瓶。假设我不想动剑圣放大招的代码,那么我们可以给他装饰一个吃血瓶的方法。C#可以用汉字作为类名,属性名,所以我就干脆用汉字。

代码如下

public interface 英雄
{
    void 放技能();
}

public class 装饰英雄 : 英雄
{
    protected 英雄 英雄实例;
    public 装饰英雄(英雄 英雄实例)
    {
        this.英雄实例 = 英雄实例;
    }

    public void 放技能()
    {
        英雄实例.放技能();
    }
}

public class 回血装饰英雄 : 装饰英雄
{
    public 回血装饰英雄(英雄 英雄实例)
        : base(英雄实例)
    {

    }

    public new void 放技能()
    {
        吃血瓶();
        this.英雄实例.放技能();
    }

    private void 吃血瓶()
    {
        Console.WriteLine("已回血");
    }
}

依次是接口,实现,装饰类,具体装饰实现。

这样我们就给剑圣加上了吃血瓶,让它在释放技能的时候不会因为血量太少被杀死。在这里假设一下,英雄不只有剑圣,还有其他的暗影猎手,牛头人,召唤先知,大法师,每个人都有自己的放技能方法,因为大家技能不一样。如果大家都要加一个吃血瓶的方法,我们就可以用这个模式,不至于给每个英雄都加一个吃血瓶,看一下调用。

public class 剑圣 : 英雄
{
    public void 放技能()
    {
        Console.WriteLine("火麟旋风");
    }
}

var 装饰 = new 回血装饰英雄(new 剑圣());
装饰.放技能();

运行结果如下

已回血
火麟旋风

加入再来个牛头人,如下

public class 牛头人 : 英雄
{
    public void 放技能()
    {
        Console.WriteLine("冲击波");
    }
}
var 装饰 = new 回血装饰英雄(new 牛头人());
装饰.放技能();

那么运行结果将会是

已回血
冲击波

OK,今天就到这里,下一节讲讲别的设计模式。

发表评论
匿名  
用户评论
暂无评论