3

我正在开发一个遗留应用程序,由于继承而存在一些缺陷,但我正在努力正确解决它。

目前 WinForms 的结构如下所示:

  • BaseForm
  • ListViewForm : BaseForm
  • ListViewFormReadOnly : ListViewForm
  • ListViewFormWithDetailForm : ListViewForm
  • DetailForm : BaseForm
  • ConcreteForm : ListViewFormWithDetailForm

BaseForm 中有一个方法,它被称为 sth like protected virtual void InitializeMyStuff(),它在继承的实例中被覆盖。

例如

public class BaseForm {
    public BaseForm() {
       //.. do stuff

       //.. do other stuff like initialize DB connection or read app.config values and initialize properties..
}

public virtual void InitializeMyStuff() {
        throw new NotImplementedException();
    }
}

public class ListViewForm : BaseForm {
    protected BindingSource GridBindingSource { get; set; }

    public ListViewForm {
       //do special stuff like adding the grid and some buttons
    }
}
public class ConcreteForm : ListViewForm {
public override void InitializeMyStuff() {
        GridBindingSource = my_bindingSource;
        SomeOtherUsefulProperty = myValue;
        Foo = new Bar();
        // etc.
    }
}

//Usage:
var myForm = new ConcreteForm();
myForm.InitializeMyStuff();

正如您可以想象的那样,这会产生一些问题,例如:-“此时我必须设置哪些内容才能使表单工作”-“哪些内容可能尚未初始化?” - “我可以使用哪些属性和方法调用”以及其他一些关于那个神奇黑盒中可能发生的事情的有趣想法。

我怎样才能重构它,以便更清楚发生了什么?请记住,这是一个包含大约 150 个或更多具体表格的项目。

我最初的想法是将这些神奇的属性封装GridBindingSource到一个对象(例如FormConfiguration)中,并在BaseForm.

例如类似的东西

public class BaseForm {
    private FormConfigObject _formConfig = new FormConfigObject();

    protected override void OnLoad()
    {
        InitializeMyStuff(_formConfig);
    }

    protected virtual void InitializeMyStuff(FormConfigObject config)
    {}
}

我在这里遇到的问题是: ListForm 的 FormConfig 对象必须具有其他属性,例如,GridBindingSource但我不能只是将派生类中的签名更改ListFormConfigObjectFormConfigObject..

任何人都可以提出可能的解决方案来摆脱这种困境吗?

// 编辑:将代码理顺到实际发生的情况,并消除构造函数违规中的虚拟调用。

4

1 回答 1

3

主要问题是:里面是否有任何对象BaseForm

  • 需要在BaseForm的构造函数中初始化
  • 取决于子类的具体实现

如果存在这样的对象,那么可能应该将它们设为多态,并BaseForm从子类传递到 ' 的构造函数中。

一个简单的例子,在许多可能的情况下:

abstract class RandomPicture
{
    public RandomPicture()
    {
        shapes = new List<Shape>();
        InitializeRandomShapes();

        // do some initial drawing calculations
    }

    protected abstract void InitializeRandomShapes();

    protected List<Shape> shapes;
}

//... subclasses initialize the shapes

这可以更改为:

abstract class RandomPicture
{
    public RandomPicture(AbstractShapeCollection shapeCollection)
    {
        shapes = shapeCollection;

        // do some initial drawing calculations
    }

    private AbstractShapeCollection shapes;
}

现在子类通过抽象对象提供所需的信息,因此基类可以继续其任务。

像这样将信息拆分为各种对象是一个很好的重构开始,因为您创建了更多更小的对象,这些对象更易于测试和管理,并揭示了您遇到的混乱的底层结构。它还有助于减少违反单一责任原则的次数。

于 2013-10-01T10:51:54.113 回答