如何设计一个注定要改变的方法

时间:2015-02-02 19:59:26

标签: c# design-patterns

我有一些插件的抽象类:

public abstract class BasePlugin
{
     public void SomeMethod(){..defaultBehaviour}.
}

这个基类将继承自几个(可能是数百个)实现。

我确实知道,以后我会以一种小的方式改变"" (但仍在改变)SomeMethod的行为。

我希望BasePlugin的现有实现继续使用相同的新实现以及使用新功能的新实现。

是否有一些模式允许我这样做?

注意:我在所有实现方面都处于领先地位,但如果新行为没有问题我无法检查数百个实现

4 个答案:

答案 0 :(得分:1)

许多模式都适合,但我认为template method pattern是合理的选择,假设您希望保持默认行为的主要部分不变:

public abstract class BasePlugin
{
  public void SomeMethod(){
      // default code before/after one or many variations 
      // to be provided by derived classes
      ...
      Variation(....);
      ...
   }

   public virtual Variation(....) {} // nothing by default
} 

答案 1 :(得分:1)

你不想这样做。如果您正在编写插件系统,则还有其他选择。这就是向插件公开一些合同。每个合约代表一个应用程序中的一种功能,插件可以扩展。

在您的插件基类中,您将定义一个注册方法:

public abstract class PluginBase
{
    public abstract void Register(IFeatureRepository repos);
}

..插件用于注册其扩展名的内容:

public class TextProcessingFilter : PluginBase, ITextProcessor
{
    public void Register(IFeatureRepository repos)
    {
        repos.Get<ITextEditor>().Subscribe(this);
    }

    void ITextProcessor.Process(TextEditorContext ctx)
    {
    }
}

新功能的好处不会破坏向后兼容性,如果您要拥有大量插件,这非常重要。只需在新版本的基本插件dll中引入新接口。

答案 2 :(得分:0)

Program to an interface, not an implementation.

对所有抽象骨架实现类使用公共接口(Plugin)时,可以添加新的抽象类(BasePluginNew)以实现新的(默认)行为。
新实现继承自这个新的抽象类BasePluginNew 旧的实现继续表现相同。

客户端引用公共Plugin接口,并且与其实现方式无关。

有关进一步讨论,请参阅http://w3sdesign.com处的GoF设计模式存储器(设计原则/接口设计)。

答案 3 :(得分:0)

我会选择策略模式(由于"Prefer composition over inheritance"等原因 - 特别是对于可能已经从另一个类继承的客户端):

public interface IPluginStrategy
{
    void SomeMethod();
}

public class OldPluginStrategy : IPluginStrategy
{
    public void SomeMethod()
    {
         // old plugin code
    }
}

public class NewPluginStrategy : IPluginStrategy
{
    public void SomeMethod()
    {
         // new plugin code which might be using OldPuginStrategy
         // through inheritance or composition
    }
}

和客户:

public class Client
{
    public Client(IPluginStrategy pluginStrategy)
    {
        ...
    }

    // use pluginStrategy's SomeMethod
}

这是在行动:

var oldClient = new Client(new OldPluginStrategy());
...
var newClient = new Client(new NewPluginStrategy());

您可以控制哪些客户端使用哪种策略,以便旧客户端可以继续使用旧的插件代码,而其他(新的?)客户端将获得新的插件。 您确实需要访问客户端&#39;代码或至少一种确保他们选择您希望他们使用的插件的方法。

请注意 - 如果您的不同插件基本上做同样的事情,并且您只想保留不同版本以避免破坏现有客户端的风险,请考虑以下事项:

  1. 这是您的插件设计不佳的症状 - 您的客户不应该知道您的插件内部。

  2. 从长远来看,这很可能非常难以维护 - 您对该插件进行了30次更改后会发生什么?你会在30个不同的客户端中运行30个不同版本的插件吗?