模板方法模式具有不同的实现方法参数

时间:2018-03-03 16:14:02

标签: c# .net design-patterns

我正在实现模板方法模式,在我的抽象类中,我有一个方法(TemplateMethod),它获取一些值并将它们传递给Step2方法。

我遇到的冲突是我的两个具体实现仅使用这些参数的部分集合,因此我不喜欢传递所有参数的想法,如果另一个具体实现需要,我不想修改此方法签名不同的参数。

我已阅读有关Parameter Object模式并看到another very similar question in SO,但我仍然不相信。有什么建议吗?

这是我的简化代码:

void Main()
{
    var concreteClassA = new ConcreteClassA();
    concreteClassA.TemplateMethod();
    var concreteClassB = new ConcreteClassB();
    concreteClassB.TemplateMethod();
}

public abstract class AbstractClass
{
    IEngine1 _engine1;
    IEngine2 _engine2;
    public void TemplateMethod() {
        Step1();
        //Get some values
        var id = _engine1.GetId();
        var name = _engine1.GetName();
        var anotherId = _engine2.GetAnotherId();
        var description = _engine2.GetDescription();
        //Pass all values to step 2
        Step2(id, name, anotherId, description);
    }
    public virtual void Step1() { }
    public virtual void Step2(int id, string name, int anotherId, int description) {}
}

public interface IEngine1 { 
    int GetId();
    string GetName();
}
public interface IEngine2
{
    int GetAnotherId();
    int GetDescription();
}

public class ConcreteClassA : AbstractClass
{
    public override void Step2(int id, string name, int anotherId, int description)
    {
        //This class only needs Id and name!
        var entity = new Entity {
            Id = id,
            Name = name
        }
        DoSomethingWithEntity(entity);
    }
    private void DoSomethingWithEntity(Entity entity) {
            //Logic here
    }
}

public class ConcreteClassB : AbstractClass
{
    public override void Step2(int id, string name, int anotherId, int description)
    {
        //This one needs other parameters
        var entity = new Entity
        {
            AnotherId = anotherId,
            Name = name,
            Description = description
        }
        DoSomethingElseWithEntity(entity);
    }
    private void DoSomethingElseWithEntity(Entity entity)
    {
        //Logic here
    }
}

public class Entity { 
    public int Id { get; set; }
    public string Name { get; set; }
    public int AnotherId { get; set; }
    public int Description { get; set;}
}

1 个答案:

答案 0 :(得分:2)

您可以尝试传递模型。您只需将模型作为参数

当您更改参数时,不会更改Step2方法签名。

只需在ParamterContext

中添加属性即可

以下是示例代码

public class ParameterContext
{
    public int id { get; set; }
    public string name { get; set; }
    public int anotherId { get; set; }
    public int description { get; set; }
}


public abstract class AbstractClass
{
    IEngine1 _engine1;
    IEngine2 _engine2;
    public void TemplateMethod()
    {
        Step1();
        //Get some values
        var id = _engine1.GetId();
        var name = _engine1.GetName();
        var anotherId = _engine2.GetAnotherId();
        var description = _engine2.GetDescription();
        //Pass all values to step 2
        Step2(new ParameterContext() {
            id = id,
            name = name,
            anotherId = anotherId,
            description = description
        });
    }
    public virtual void Step1() { }
    public virtual void Step2(ParameterContext parameter) { }
}

public interface IEngine1
{
    int GetId();
    string GetName();
}
public interface IEngine2
{
    int GetAnotherId();
    int GetDescription();
}

public class ConcreteClassA : AbstractClass
{
    public override void Step2(ParameterContext para)
    {
        //This class only needs Id and name!
        var entity = new Entity
        {
            Id = para.id,
            Name = para.name
        };
        DoSomethingWithEntity(entity);
    }
    private void DoSomethingWithEntity(Entity entity)
    {
        //Logic here
    }
}

public class ConcreteClassB : AbstractClass
{
    public override void Step2(ParameterContext para)
    {
        //This one needs other parameters
        var entity = new Entity
        {
            AnotherId = para.anotherId,
            Name = para.name,
            Description = para.description
        };
        DoSomethingElseWithEntity(entity);
    }
    private void DoSomethingElseWithEntity(Entity entity)
    {
        //Logic here
    }
}

修改

另一种方式是

IEngine1IEngine2接口声明为保护,在AbstractClass类中,您可以使用他们的方法而不是传递参数。

public abstract class AbstractClass
{
    public AbstractClass() { }

    public AbstractClass(IEngine1 eng1, IEngine2 eng2)
    {
        _engine1 = eng1;
        _engine2 = eng2;
    }

    protected IEngine1 _engine1;
    protected IEngine2 _engine2;
    public void TemplateMethod()
    {
        Step1();
        //Get some values
        //var id = _engine1.GetId();
        //var name = _engine1.GetName();
        //var anotherId = _engine2.GetAnotherId();
        //var description = _engine2.GetDescription();
        //Pass all values to step 2
        Step2();
    }
    public virtual void Step1() { }
    public virtual void Step2() { }
}

public interface IEngine1
{
    int GetId();
    string GetName();
}
public interface IEngine2
{
    int GetAnotherId();
    int GetDescription();
}

public class ConcreteClassA : AbstractClass
{
    public override void Step2()
    {
        //This class only needs Id and name!
        var entity = new Entity
        {
            Id = _engine1.GetId(),
            Name = _engine1.GetName()
        };
        DoSomethingWithEntity(entity);
    }
    private void DoSomethingWithEntity(Entity entity)
    {
        //Logic here
    }
}

public class ConcreteClassB : AbstractClass
{
    public override void Step2()
    {
        //This one needs other parameters
        var entity = new Entity
        {
            AnotherId = _engine2.GetAnotherId(),
            Name = _engine1.GetName(),
            Description = _engine2.GetDescription()
        };
        DoSomethingElseWithEntity(entity);
    }
    private void DoSomethingElseWithEntity(Entity entity)
    {
        //Logic here
    }
}

public class Entity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int AnotherId { get; set; }
    public int Description { get; set; }
}