用户可扩展类的框架设计?

时间:2014-09-22 13:57:08

标签: design-patterns architecture

考虑以下类图:

Framework design - class diagram

ModelAModelB是框架类,MyModelAMyModelB是框架用户定义的类。

框架使用proceed()方法,并由用户实现。显然,实现可以使用ModelA

的方法

用户应该可以优化ModelA类(例如添加其他数据记录)并将扩展类(MyModelA)的对象传递给框架来使用。

现在的问题是以某种方式设计框架,proceed()的实现也可以使用MyModelA的方法,在本例中为getMyValue()

是否有解决此问题的标准设计模式?

以下可能的解决方案也可以澄清问题:

1。铸造

如果框架的用户知道他正在使用哪些ModelA类,他可以将ModelA参数转换为proceed()实现中的正确类型。 当然这有点麻烦而且不干净。

2。使用模板参数

为了保持类型安全,可以使用类型参数对框架进行参数化,该参数用于参数化ModelB。在Java中:

public class ModelB<T extends ModelA> {
  public abstract void proceed(T data);
}

通过这种方式,可以根据需要进行以下操作:

public class MyModelB extends ModelB<MyModelA> {
  public abstract void proceed(MyModelA data) {
    data.getMyValue();
  }
}

但这可能会非常不方便,特别是如果更多类出现相同的问题,您将不得不引入多个类型参数。 此外,它似乎不太灵活。

3。在ModelA [有限]

中提供基本数据模型

如果只希望用户能够将自定义数据添加到ModelA,那么提供一个或多或少灵活的数据存储系统是否是一个相当大的解决方案?

示例:A&#34;树字典&#34;,即可以存储标准数据类型的键值对,并使用多级密钥对其进行索引:data.getString(["fruits", "apple", "small"])

更新1

澄清要求是什么: 可以认为ModelA代表游戏玩家,ModelB代表玩家可以执行的某些动作。该框架定义了一个通用的玩家类和一个抽象的proceed()方法。使用该框架的应用程序在MyModelA中添加了可在MyModelB中的操作中使用的播放器功能。应用程序不会直接调用这些操作,而是由框架调用(例如,应用程序调度调用)。

1 个答案:

答案 0 :(得分:0)

真正需要定义

public abstract class ModelB
{
   public abstract void Proceed(ModelA a);
}

public abstract class ModelB
{
    public abstract void Proceed();
}

如果您实际上没有在基类ModelB中使用ModelA?

它可能看起来像:

类似命令的解决方案

public abstract class ModelB
{
    public abstract void Proceed();
}

public class MyModelB : ModelB
{
    //inject via constructor
    private readonly MyModelA _a;
    public void Proceed() 
    {
       //do somthing with a
    }
}

public abstract class ModelB
{
    public abstract void Proceed(ModelA a);
    protected abstract ModelA ModelA { get; }
}

public class MyModelB : ModelB
{
    //inject via constructor
    private readonly MyModelA _a;
    public void Proceed() 
    {
       //do somthing with a
    }

    protected override ModelA ModelA
    {
        get { return _a; }
    }
}

以这种方式思考,看看命令模式:

public abstract class Command
{
    public abstract void Run();

    public abstract ModelA Argument { get; }
}

public abstract class ModelB
{
    //not abstract
    public void Proceed(Command command)
    {
        command.Run();
    }        
}

好的,如果你真的必须这样做,我认为安全演员是最好的解决方案:

安全投射

public class MyModelB : ModelB
{
    public override void Proceed(ModelA a)
    {
        if (a is MyModelA)
        {
            var myA = (MyModelA) a;
            //do something with a
        }
    }

}