将两个非常相似的类重构为一个

本文关键字:重构 一个 非常 两个 相似 | 更新日期: 2023-09-27 18:06:17

这是第一个类:

public class TextBoxInt : TextBox
{
    public int min;
    public int max;
    public Value<int> value;
    public virtual void Update(object sender, EventArgs e)
    {
        int newValue;
        if (int.TryParse(Text, out newValue))
        {
            if (newValue < min || newValue > max)
            {
                //do thing A
            }
            value.Set(newValue);
            Text = value.Get().ToString();
        }
        else
        {
            Text = value.Get().ToString();
            Focus();
        }
    }
    public TextBoxInt(Value<int> value, int min, int max)
    {
        this.value = value;
        this.min = min;
        this.max = max;
        Text = value.Get().ToString();
        LostFocus += new EventHandler(update);
    }
}

这是第二类:

public class TextBoxFloat : TextBox
{
    public float min;
    public float max;
    public Value<float> value;
    public virtual void Update(object sender, EventArgs e)
    {
        float newValue;
        if (float.TryParse(Text, out newValue))
        {
            if (newValue < min || newValue > max)
            {
                //do thing A
            }
            value.Set(newValue);
            Text = value.Get().ToString();
        }
        else
        {
            Text = value.Get().ToString();
            Focus();
        }
    }
    public TextBoxFloat(Value<float> value, float min, float max)
    {
        this.value = value;
        this.min = min;
        this.max = max;
        Text = value.Get().ToString();
        LostFocus += new EventHandler(update);
    }
}

此外,这是Value类:

public class Value<T>
{
    private T value;
    private List<IValueListener<T>> listeners = new List<IValueListener<T>>();
    public Value(T value)
    {
        this.value = value;
    }
    public T Get()
    {
        return value;
    }
    public void Set(T value)
    {
        this.value = value;
        foreach (IValueListener<T> listener in listeners)
        {
            listener.ValueUpdated(this);
        }
    }
    public void AddListener(IValueListener<T> listener)
    {
        listeners.Add(listener);
    }
    public void RemoveListener(IValueListener<T> listener)
    {
        listeners.Remove(listener);
    }
}

正如你所看到的,前两个类基本上是同一个类。唯一的区别是类型。第一个是int,另一个是float。如果我能把这两个类组合成一个类,我似乎会制作出更好的代码。

如果是int类,我可以将minmax设置为float,并在需要时将它们强制转换为int。当类型是int.时,我只会确保我通过"完整"浮动

有没有什么方法可以在不复制Update()方法(If int do codeForInt, else if float do sameCodeButForFloat(的情况下做到这一点?

此外,即使我复制了代码,我也会遇到value.Set(newValue);的问题——在一种情况下,newValue将是int,在另一种情况中,它将是float,并且我不能将任何一个转换为T

还有,有没有办法限制泛型类型?要指定它只能是int还是float?

我应该把它们作为两个阶级,还是有办法把它们统一起来?

将两个非常相似的类重构为一个

您可以创建一个泛型类,而不是创建单独的类。

public class BoundedTextBox<T> : TextBox where T : IComparable<T> ...

声明T实现IComparable<T>将允许您在设置操作期间检查T是否在边界内。

if (newValue.CompareTo(min) <= 0 || newValue.CompareTo(max) >= 0)
{
    // do thing A
}

让一个抽象的TextBox<T>类继承自TextBox类,其中TextBox<T>有一个新的abstract string GetValue()方法怎么样?您将有实现GetValue()TextBoxFloat类,它将执行float特定的逻辑,类似地,TextBoxInt类也将执行。你的TextBox<T>会有点像

public abstract class TextBox<T> : TextBox
{
    public T min;
    public T max;
    public Value<T> value;
    public virtual void Update(object sender, EventArgs e)
    {
        Text = GetValue();
        Focus();
    }
    public TextBoxFloat(Value<T> value, T min, T max)
    {
        this.value = value;
        this.min = min;
        this.max = max;
        Text = value.Get().ToString();
        LostFocus += new EventHandler(update);
    }
    public abstract string GetValue();
}

正如@flkes所说,泛型类是实现这一点的方法。你可以尝试以下方法:(你可以在这里找到一个很好的例子(

    public abstract class TextBoxBase
    {
        public abstract object GetMin();
        public abstract object GetMax();
        public abstract object GetValue();
    }
    public abstract class TextBox<T> : TextBoxBase
    {
        public T min { get; set; }
        public T max { get; set; }
        public T value { get; set; }
        public virtual void SetTextBox(T mn, T mx, T val)
        {
            min = mn;
            max = mx;
            value = val;
        }
        public override object GetMin() { return min; }
        public override object GetMax() { return max; }
        public override object GetValue() { return value; }
    }
    public class TextBoxInt : TextBox<int>
    {
        public override void SetTextBox(int mn, int mx, int val)
        {
            min = mn;
            max = mx;
            value = val;
        }
    }
    public class TextBoxFloat : TextBox<float>
    {
        public override void SetTextBox(float mn, float mx, float val)
        {
            min = mn;
            max = mx;
            value = val;
        }
    }