用于克服反向构造函数顺序的设计模式?

时间:2019-02-21 19:57:10

标签: c# design-patterns constructor

我遇到以下问题:

基类希望接收一些数据,但是数据是由派生类构造函数初始化的,在C#中,派生类构造函数在调用基构造函数之后被调用。

上下文/我要解决的问题:

让我们称之为基类Track,它的作用是建立一个代表视频游戏轨道的网格。

派生类,例如Track1每个都从特定的文件格式中获取跟踪数据,但有显着差异,因此禁止在基类Track中实现整个代码。

Track的主要工作是抽象派生类派生的数据,为此它具有派生类必须实现的抽象成员,例如: int GetVertexCountVector3 GetVertex(int)

请多考虑一个IPicture接口,它可以从不同的格式(例如, BMP,JPEG,然后将整个内容作为抽象返回。

我面临的问题:

在C#中,基类构造函数在派生类构造函数之前被调用,但我必须在派生的类构造函数中初始化某些内容,而该构造函数又必须传递给 base 类构造函数。在进行此操作时,我希望成员是不变的,即readonly

问题:

如何首先在派生类构造函数中运行一些代码,以便将结果传递给基本构造函数?

答案:

跟随 @Kit 回答,这就是我最终的做法,这很好:

enter image description here

具有讽刺意味的是,它最终成为了一个类似于C的API:)

2 个答案:

答案 0 :(得分:1)

假设您不需要派生类的实例即可执行所需的逻辑,则可以在调用基本构造函数之前从派生构造函数调用静态方法。

这是一个简单的例子

public class Base
{
     protected Base(SomeType data)
     {
         // base logic using data
     }
}

public class DerivedOne : Base
{
    public DerivedOne(int some, string data) : base(DerivedLogic(some, data))
    {
        ...
    }

    private static SomeType DerivedLogic(int some, string data) => ...
}

public class DerivedTwo : Base
{
    public DerivedTwo (string moreStuff) : base(DerivedLogic(moreStuff))
    {
        ...
    }

    private static SomeType DerivedLogic(string moreStuff) => ...
}

这按以下顺序运行:

  1. 静态方法DerivedLogic
  2. 基类构造函数(使用DerivedLogic中的值)
  3. 派生构造函数

现在,这有点奇怪。更好的是,派生逻辑根本不属于派生类。我什么意思我的意思是,您有第三个类,该类传递给派生的构造函数,然后传递给基本构造函数。那会给你同样的效果。

public class Base
{
     protected Base(SomeOtherType dataWrapper)
     {
         var data = dataWrapper.DerivedLogic();
         // base logic using data
     }
}

public class DerivedOne : Base
{
    public DerivedOne(SomeOtherType otherType) : base(otherType)
    {
        ...
    }
}

或者在调用任何构造函数之前先计算SomeType,然后将其传递。这两种方法中的任何一种都是更好的设计,因为它遵循SRP

  1. 负责其工作的基类。
  2. 构建音轨的逻辑只有这一责任。
  3. 派生类承担单一责任。

答案 1 :(得分:0)

没有一种真正优雅的方法来精确地完成您所要的东西,但是我会怀疑这是否真的必要。在构造函数中看到逻辑通常是一种代码味道。

您可以采用许多其他方法,例如使用静态Create()方法。

class Derived : Base
{
    private readonly object _o;

    private Derived(object o, string s) : base(s)
    {
        _o = o;
    }

    public static Derived Create(string path)
    {
        var o = new object();// initialize from path
        var s = o.ToString(); // get s from o.
        return new Derived(o, s)
    }
}

您还可以考虑在继承中使用合成:

class Base
{
    private readonly string _s;

    public Base(string s)
    {
        _s = s.ToLower();
    }
}

class Derived
{
    private readonly object _o;
    private readonly Base _b;

    public Derived(string path)
    {
        _o = new object();// initialize from path
        _b = new Base(_o.ToString());
    }       
}

但是,在不知道您的实际目标和约束是什么的情况下,很难知道哪种方法合适。您已告诉我们您想如何解决问题,而不是告诉我们您要解决的问题