如何覆盖方法保存模板方法模式

时间:2019-01-02 13:19:48

标签: c# asp.net templates design-patterns

我确实有一个抽象类,在构造函数上,我调用了在同一类上声明的抽象方法,而我这样做是因为我想强迫所有派生类不仅实现我的抽象方法,而且还强制调用它(我认为这是Template Method模式的来源)。

顺便说一句:我知道这不是确保所有内容都能正确写入的最佳方法,但是由于外部问题,我希望通过不好的实施来最大程度地减少以后的问题。该代码段如下:

public abstract class Generic
{
    public Generic()
    {
        Console.WriteLine("This is the generic");

        this.SetRules();
    }

    protected abstract void SetRules();
}

好吧,在我的派生类之一上,需要在声明中设置一个私有变量,我想在重写方法中使用此变量。由于我不知道我的每个派生类都需要多少可能性,因此我想根据需要在每个我的派生类中声明它。下面的示例:

public class Derivated2 : Generic
{
    private int _parameter;

    public Derivated2(int parameter)
    {
        this._parameter = parameter;
    }

    protected override void SetRules()
    {
        int x = 0;
        x = 1 + 3;

        Console.WriteLine(String.Concat("This is the derivated2 with x: ", x, "; _parameter: ", _parameter));
    }
}

现在有问题;

当我调用派生类2时,我无法使用/查看在声明中指定的变量值:

public static void Main()
{
    Derivated2 _class1 = new Derivated2(2);
}

我的输出是:

This is the generic
This is the derivated2 one with x: 4; _parameter: 0

如何在覆盖的asbtract方法上查看/使用变量? 如果不能,那么无论开发人员做什么,并且可以在其派生类中使用私有变量的方法都可以调用,以确保SetRules方法安全的最佳方法是什么?

这是我完成的完整代码:

Calling SetRules on Abstract Generic Class

Calling SetRules on Derivated Class

3 个答案:

答案 0 :(得分:1)

问题是您正在调用Generic构造函数,该构造函数将在调用Derivated2构造函数之前调用SetRules,这意味着尚未设置参数。你可以试试 这个。

public abstract class Generic
{
    public Generic(int parameter)
    {
        Console.WriteLine("This is the generic");

        this.SetRules(parameter);
    }

    protected abstract void SetRules(int paramter);
}

public class Derivated2 : Generic
{

    public Derivated2(int parameter) : base(parameter){ }

    protected override void SetRules(int parameter)
    {
        int x = 0;
        x = 1 + 3;

        Console.WriteLine(String.Concat("This is the derivated2 with x: ", x, "; _parameter: ", parameter));
    }
}
public static void Main()
{
    Derivated2 _class1 = new Derivated2(2);
}

正如您所说,每次要创建一个新类都必须调用SetRules并不是很好,所以这意味着您不必(迅速将其放在一起,因此需要对其进行修复)

public abstract class Generic
{
    public Generic()
    {
        Console.WriteLine("This is the generic");
    }

    public abstract void SetRules();
}

public sealed class Derivated2 : Generic
{
    int _param;

    public Derivated2(RulesWithParameters rules) {
        _param = rules.Parameter;
    }

    public override void SetRules()
    {
        int x = 0;
        x = 1 + 3;

        Console.WriteLine(String.Concat("This is the derivated2 with x: ", x, "; _parameter: ", _param));
    }
}
public void Main()
{
    var rules = new RulesWithParameters{
        Parameter = 5
    };
    var _class1 = FactoryMethod<Derivated2>(rules);

    var _class2 = FactoryMethod<Derivated1>(null);
}

public class Derivated1 : Generic
{
    public Derivated1(Rules rules)
    {

    }
    public override void SetRules()
    {
        Console.WriteLine("This is the derivated1");
    }
}
public class Rules
{
    public string RuleName {get; set;}
}

public class RulesWithParameters : Rules{
    public int Parameter { get; set;}
}

public Generic FactoryMethod<T>(Rules rules) where T : Generic
{
    T instance = (T)Activator.CreateInstance(typeof(T), rules);;
    instance.SetRules();
    return instance;
}

答案 1 :(得分:0)

我想C#中的构造函数不是多态的,因此您不能从构造函数中调用可重写的方法。您可以阅读以下文档:MSDN article

通常,使用这种方法对我来说似乎也是一个坏习惯。抽象类的构造函数不知道您的后代类的实现详细信息,因此也不应了解,因此在其中放置Derivated2的初始化是不正确的。尝试将初始化代码放在其他位置。

答案 2 :(得分:0)

如果SetRules方法可以是静态的而不是实例,则可以添加静态构造函数,并且可以在该构造函数内部调用SetRules方法。如果不是的话,工厂的想法似乎是最好的清洁方法。