装饰者模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰者模式相关的知识,希望对你有一定的参考价值。

前景 : 有一个主角(你) , 拥有基础战斗力 , 当你穿上了装备(此装备可以为你获得战力的加成提升) , 比如穿了一个护腕那你的战斗力需要在基础战力的基础上加上护腕加成的战斗力,如果再穿上了头盔 , 那么你的战斗力就是基础战斗力 + 护腕加成 + 头盔加成

这个场景在RPG游戏中很常见. 下面我们使用装饰者模式去实现它.

一 :所有加成类的基类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DecoratorPatternDemo.com
{
    /// <summary>
    /// 所有加成战斗加成基类
    /// </summary>
    public abstract class BaseAddtition
    {
        /// <summary>
        /// 被装饰者
        /// </summary>
        private BaseAddtition _decor = null;
        /// <summary>
        /// 本加成的power
        /// </summary>
        protected Int32 _power = 0;
        /// <summary>
        /// 战斗力描述
        /// </summary>
        protected string _describe = string.Empty;
        /// <summary>
        /// </summary>
        /// <param name="describe">描述</param>
        /// <param name="power">战斗力</param>
        /// <param name="decor">被装饰者</param>
        public BaseAddtition( string @describe, Int32 @power = 0 , BaseAddtition @decor = null)
        {
            this._describe = @describe;
            this._power = @power;
            this._decor = @decor;
        }
        /// <summary>
        /// 统计战斗力
        /// </summary>
        /// <returns></returns>
        public Int32 StatisticsPower()
        {
            if (null != this._decor)
            {
                return this._decor.StatisticsPower() + this._power;
            }
            else
            {
                return this._power;
            }
        }
        /// <summary>
        /// 获取描述
        /// </summary>
        public abstract string Describe { get; }
    }
}

二 : 各种加成

①:战靴

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DecoratorPatternDemo.com.cn
{
    /// <summary>
    /// 战靴加成战斗力
    /// </summary>
    public sealed class BootsAddtition : BaseAddtition
    {
        public BootsAddtition(string describe, Int32 power, BaseAddtition decor) : base(describe, power, decor)
        {
        }

        public override string Describe
        {
            get { return string.Format(@"{0}{1}的战斗力:{2}", this._describe,"加成", this._power); }
        }
    }
}

②:护膝

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DecoratorPatternDemo.com.cn
{
    /// <summary>
    /// 护膝的加成战斗力
    /// </summary>
    public sealed class KneepadAddtition : BaseAddtition
    {
        public KneepadAddtition(string describe, Int32 power, BaseAddtition decor) : base(describe, power, decor)
        {

        }

        public override string Describe
        {
            get { return string.Format(@"{0}{1}的战斗力:{2}", this._describe,"加成", this._power); }
        }
    }
}

三 : 主角

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DecoratorPatternDemo.com.cn
{
    /// <summary>
    /// 主角的基本战斗力
    /// </summary>
    public sealed class LeadBasePower : BaseAddtition
    {
        public LeadBasePower(string describe, Int32 power) : base(describe , power, null )
        { }

        public override string Describe
        {
            get { return string.Format(@"{0}{1}的战斗力:{2}", this._describe , "基础", this._power); }
        }
    }
}

四 : 测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DecoratorPatternDemo.com;
using DecoratorPatternDemo.com.cn;

namespace DecoratorPatternDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseAddtition @leader = new LeadBasePower(@"主角", 100000);
            Console.WriteLine(@leader.Describe);
            //用战靴来装饰主角
            BaseAddtition @boots = new BootsAddtition(@"战靴", 12, @leader);
            Console.WriteLine(@boots.Describe);
            //用护膝装饰战靴(间接装饰主角)
            BaseAddtition @kneepad = new KneepadAddtition(@"护膝", 200, @boots);
            Console.WriteLine(@kneepad.Describe);

            //计算综合战斗力
            Console.WriteLine(@"总战斗力 : {0}", @kneepad.StatisticsPower());
            Console.Read();
        }
    }
}

注意层层装饰 , 递归调用

五:结果

技术分享图片

?????为何需要考虑装饰者模式 : 当加入新的装备后 ???? 可以直接继承BaseAddtition抽象类.实现了开闭原则.

以上是关于装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式之装饰者模式

设计模式整理_装饰者模式

设计模式-装饰者模式(Go语言描述)

设计模式-装饰者模式(Go语言描述)

装饰者模式

设计模式 之 装饰者模式