Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 避免向接口添加/扩展方法_Oop_Design Patterns_Interface - Fatal编程技术网

Oop 避免向接口添加/扩展方法

Oop 避免向接口添加/扩展方法,oop,design-patterns,interface,Oop,Design Patterns,Interface,我有一个场景,我当前的界面看起来像 public interface IMathematicalOperation { void AddInt(); } 一年后,我预计该界面将使用AddFloat方法进行扩展,并且预计已有100名用户使用该界面。当我在一年后用一个新方法扩展接口时,我不希望这100个类被改变。 那么,我该如何应对这种情况呢?是否已有任何设计模式可用于处理这种情况 注意:我知道我可以有一个抽象类来实现这个接口并使所有方法都是虚拟的,这样客

我有一个场景,我当前的界面看起来像

    public interface IMathematicalOperation
    {
         void AddInt();
    }
一年后,我预计该界面将使用AddFloat方法进行扩展,并且预计已有100名用户使用该界面。当我在一年后用一个新方法扩展接口时,我不希望这100个类被改变。 那么,我该如何应对这种情况呢?是否已有任何设计模式可用于处理这种情况

注意:我知道我可以有一个抽象类来实现这个接口并使所有方法都是虚拟的,这样客户端就可以从这个类而不是接口继承并重写这些方法。当我添加一个新方法时,只会更改抽象类,对该方法感兴趣的客户机将重写该行为(最小化更改)。 有没有其他方法可以达到相同的结果(比如有一个名为Add的方法,根据特定的条件,它将进行浮点加法或整数加法)

编辑1:


添加到接口的新方法还需要与现有方法一起自动调用(如责任链模式)。

我至少可以想到两种可能的解决方案:

  • 从旧接口派生新接口

    public接口图像化操作
    {
    void AddInt();
    }
    IFloatingPointMathematicalOperation的公共接口:IMathematicalOperation
    {
    void AddFloat();
    }

  • 只需要一个包含新方法的并行接口,并让所有需要新接口的类都从中派生出来


我建议使用第二种解决方案,因为我不明白您为什么希望更改已建立的接口。

我不久前遇到了类似问题,发现最好的方法不是尝试扩展现有接口,而是提供不同版本的接口,每个新接口都提供额外的功能。随着时间的推移,我发现没有定期添加功能,可能一年一次,所以添加额外的接口从来都不是一个真正的问题

例如,这是您的第一个界面版本:

public interface IMathematicalOperation
{
    void AddInt();
}
public class MathematicalOperationImpl : IMathematicalOperation, IMathematicalOperation2
{
    public void AddInt()
    {
    }

    public void AddFloat()
    {
    }
}
然后,该接口将在如下类上实现:

public class MathematicalOperationImpl : IMathematicalOperation
{
    public void AddInt()
    {
    }
}
然后,当您需要添加新功能(即创建版本2)时,您可以创建另一个名称相同但结尾带有“2”的接口:

public interface IMathematicalOperation2 : IMathematicalOperation
{
    void AddFloat();
}
将扩展
MathematicalOperationImpl
以实现此新接口:

public interface IMathematicalOperation
{
    void AddInt();
}
public class MathematicalOperationImpl : IMathematicalOperation, IMathematicalOperation2
{
    public void AddInt()
    {
    }

    public void AddFloat()
    {
    }
}

您所有的新客户机/未来客户机都可以开始使用版本2接口,但您现有的客户机将继续工作,因为他们只知道接口的第一个版本

提供的选项在语法上是可行的,但很明显,它们不适用于任何以前的用户

更好的选择是使用

当您考虑OO代码的细节时,最好理解该模式

this.foo(); // is identical to
foo(this); 
请记住,每次实例调用都会传递一个隐藏的“this”参数。 访问者模式试图做的是使用

让我们更进一步

public interface MathematicalOperation
{
    void addInt();
    void accept(MathVisitor v);
}

public interface MathVisitor {

    void visit(MathematicalOperation operation);

}

public class SquareVistor implements MathVisitor {

    void visit(MathematicalOperation operation) {
        operation.setValue(operation.getValue() * 2);
    }

}

public abstract class AbstractMathematicalOperation implements MathematicalOperation {
   public void accept(MathVisitor f) {
     f.visit(this); // we are going to do 'f' on 'this'. Or think this.f();
   }
}

public class MyMathOperation extends AbstractMathematicalOperation {

}

someMathOperation.visit(new SquareVisitor()); // is now functionally equivalent to
someMathOperation.square();

最好的办法是,根据访问者的需求推出初始接口,然后立即推出一个抽象子类,该子类给出了这个默认实现,因此它可以直接在中进行(如上所述的类)。然后每个人都可以扩展它。我想您会发现,这为您提供了所需的灵活性,并使您能够使用遗留类

为什么不扩展它呢?实现这个接口的100个类不会受到影响吗?所以我想避免这个问题。不,他们不会受到影响。他们只依赖旧的接口。好的,我明白你所说的扩展它的意思。我假设扩展意味着修改旧接口。我只想依赖一个接口(因为我是提供者,我需要调用方法,我不想做类型检查),所以我想避免添加新接口和新方法。如果你想依赖新接口,类必须实现新函数,所以它们必须改变。我假设您有一个新的上下文,在这里使用这个新函数,所以这里需要新接口,否则就使用旧接口。是的,我也考虑过这个解决方案,但希望通过添加/扩展新接口来避免类型检查。好的,我的场景更像是,我想要一个名为IConverter的接口,其中包含一个名为ConvertToFormatX()的方法。但随着时间的变化,我希望在一段时间内出现一个名为ConvertToFormatY()的新方法,但不是现在。另外,当我想调用接口中的方法时,我想链接这些方法。例如,当前只调用ConvertToFormatX,当新方法被添加时,也调用ConvertToFormatX,如果另一个方法被添加,也调用第三个方法。