如何概括属性模式

时间:2018-02-18 20:38:36

标签: c#

我的类具有多个属性,这些属性具有明确定义的名称和功能,但具有相同的实现。例如:

class Stats
{
    private int attack;
    public int Attack
    {
        get =>
            HasBuff ? attack + 1 : attack;
        set
        {
            if (value < 1 || value > 10)
                throw new ArgumentOutOfRangeException("Invalid value");
            attack = value;
        }
    }

    public int Defense {...}
    public int Speed {...}
}

DefenseSpeed的实施方式与Attack类似。如何概括此结构以避免冗余并使更改更容易?

3 个答案:

答案 0 :(得分:5)

制作另一个课程来概括统计数据:

public class Stat
{
    public bool HasBuff { get; set; }

    private int _stat;
    public int Score
    {
        get => HasBuff ? _stat + 1 : _stat;
        set => _stat = value;
    }
}

然后将其用于您的每项技能:

public class CombatStats
{
   public Stat Attack { get; } = new Stat();
   public Stat Defense { get; } = new Stat();
   public Stat Speed { get; } = new Stat();
}

调用代码如下所示:

var ninja = new Ninja();
ninja.skills = new CombatStats();
var attackStrength = ninja.skills.Attack.Score;

作为进一步改进,可以使用隐式运算符来避免对象创建并调用Score:

public class Stat
{
    ...

    public static implicit operator int(Stat stat)
    {
        return stat.Score;
    }

    public static implicit operator Stat(int value)
    {
        return new Stat()
        {
            Score = value
        };
    }
}

这使得更改对于w.r.t写的客户端代码是透明的。问题中的例子:

ninja.skills = new CombatStats(){
    Attack = 5,
    Defense = 2
}
int attack = ninja.skills.Attack;

答案 1 :(得分:3)

需要考虑的一种方法:

class Stats
{
    // other existing code here

    private int defense;

    public int Defense
    {
        get
        {
            return GetValue(defense);
        }
        set
        {
            SetValue(value, ref defense);
        }
    }

    private int GetValue(int value)
    {
        return HasBuff ? value + 1 : value;
    }

    private void SetValue(int value, ref int target)
    {
        if (value < 1 || value > 10)
            throw new ArgumentOutOfRangeException("Invalid value");
        target = value;
    }
}

Attack等现在与Defence基本相同,但是将attack而不是defense传递给GetValueSetValue }。

答案 2 :(得分:2)

我会选择合成

统计:

    public class Stats
    {
        private readonly StatProperty _defense;
        private readonly StatProperty _attack;
        private readonly StatProperty _speed;

        public Stats()
        {
            _defense = new StatProperty(this);
            _attack = new StatProperty(this);
            _speed = new StatProperty(this);
        }

        public int Defense
        {
            get => _defense.Value;
            set => _defense.Value = value;
        }

        public int Attack
        {
            get => _attack.Value;
            set => _attack.Value = value;
        }
        public int Speed
        {
            get => _speed.Value;
            set => _speed.Value = value;
        }

        public bool HasBuff { get; set; }

    }

StatProperty:

    public class StatProperty
    {
        public Stats Stats { get; }

        public StatProperty(Stats stats)
        {
            Stats = stats;
        }

        private int _value = 1;
        public int Value
        {
            get => Stats.HasBuff ? _value + 1 : _value;
            set
            {
                if (value < 1 || value > 10)
                    throw new ArgumentOutOfRangeException("Invalid value");
                _value = value;
            }
        }
    }

我需要更多细节才能知道它是否是最佳选择。

如果你想在类Stats上使用它,你也可以将StatProperty作为内部,如果你不想在你的库或嵌套私有类之外显示它