2

不止一次,我发现自己在使用一个封闭的类(我无法修改它),我希望实现一个适合我需要的窄接口。我的客户端代码应该拥有该接口,但我不知道有任何机制可以宣布这个封闭类是我的缩小接口的实现。

我试图让这个类被传递(依赖注入)到我的代码(组合)中,但也允许其他任何可以支持窄接口的东西。在其他语言中,鸭子打字使这变得微不足道。虽然我在java中,所以我希望必须编写一个完整的其他类来包装封闭类以实现这一点。有没有我想念的方法?

谢谢


编辑以解决欺骗:

接口隔离原则没有提到封闭类问题,这是这个问题的重点。请重新考虑标记为这个特定问题的欺骗。


这个问题: Interface Segregation Principle-Program to an interface,有一个很好的接口隔离原则示例:

class A {
   method1()
   method2()
   // more methods
   method10()
}
class B {
    A a = new A()

}

会变成

interface C {
      method1()
      method2()
}



class A implements C{
      method1()
      method2()
      // more methods
      method10()
  }
  class B {
       C c = new A()

 }   

但请注意它如何需要对 A 类进行更改。如果 A 对修改关闭,我如何干净地完成同样的事情?

4

3 回答 3

1

根据情况,一种可能性是将所有类包装在一个包装类中,该包装类公开所述接口,我的意思是这样的:

public class UnmodifyableObject {
    public void method1();
    public void method2();
    public void method3();
    public void method4();
}

然后你希望界面看起来像:

public interface MyInterface {
    public void method1();
    public void method2();
}

作为一种解决方案,您可以将您的包装UnmodifyableObjectWrappedUnmodifyableObject

public class WrappedUnmodifyableObject implements MyInterface {
    private final UnmodifyableObject unmodifyableObject;

    public WrappedUnmodifyableObject(final UnmodifyableObject unmodifyableObject) {
        this.unmodifyableObject = Objects.requireNonNull(unmodifyableObject, "unmodifyableObject");
    }

    @Override
    public void method1() {
        unmodifyableObject.method1();
    }

    @Override
    public void method2() {
        unmodifyableObject.method2();
    }

    public void method3() {
        unmodifyableObject.method3();
    }

    public void method4() {
        unmodifyableObject.method4();
    }
}

它只是委托所有方法,当然它实现了接口。

需要注意的一些重要事项是: - 您应该使用组合而不是继承,仅扩展类可能看起来更容易,但您无法控制该代码,它可能会删除方法,甚至可能是final. - 这确实意味着你必须做很多工作。- 如果您不想自己做这项工作,您可能需要在执行之前或加载类之前查看工具来更改字节码。

该对象的使用将通过:

UnmodifyableObject unmodifyableObject = someExternalMethodCall();
MyInterface myInterfaceObject = new WrappedUnmodifyableObject(unmodifyableObject);
于 2014-05-21T11:13:47.930 回答
0

Mark Peters 建议简单地扩展封闭类以避免包装器。由于他还没有根据它发布答案,我会写一个。

我通常避免继承,而是将组合作为一种下意识的反应,但在这种情况下,它似乎确实有优点。编写包装器的主要原因只是将编码的罪恶从客户端方法转移到包装器中。因此,唯一获得的是间接级别。如果这就是我们得到的全部,我们可以找到一种更简单的方法来获得它,为什么不呢?

下面是一些代码,它在一个非常流行且非常封闭的库类上添加了一个非常狭窄的角色接口:ArrayList。

public class MainClass {

    public static void main(String[] args) {

       OpenArrayList<String> ls = new OpenArrayList<String>();
       ShowClient client = new ShowClient(ls);

       ls.add("test1");       
       client.show();

       ls.add("test2");       
       client.show();
    }
}

//Open version of ArrayList that can implement roleinterfaces for our clients
public class OpenArrayList<E> extends ArrayList<E> implements ShowState {
    private static final long serialVersionUID = 1L;
}

//Roleinterface for ShowClient
public interface ShowState {
    public int size();
    public String toString(); 
}

//Show method programmed to a roleinterface narrowed specifically for it
public class ShowClient {

    private ShowState ss;

    ShowClient(ShowState ss) {
        this.ss = ss;
    }

    void show() {
        System.out.println( ss.size() );
        System.out.println( ss.toString() );
    }
}

那么,如果你打算在使用一个对修改关闭的类时进行接口隔离,是否有理由不这样做呢?

于 2014-05-23T03:34:35.573 回答
0

使用一个或多个适配器。适配器是一种包装器,它可以更改被包装类的接口,而无需更改其源。

class A {
   method1()
   method2()
   // more methods
   method10()
}

interface SegregatedI1 {
  method1();
}

interface SegregatedI2 {
  method2();
  method3();
}

class ASegregatedI1Adapter implements SegregatedI1 {
    private final A a;

    AI1Adapter(A a){
       this.a = a;
    }

    public void method1(){
      a.method1();
    }
}

请注意,它A可能是一个接口或一个final类。另请注意,适配器可以实现多个隔离接口,或者您可以为每个接口设置单独的适配器(我希望后者保持单一职责内联)。

于 2014-05-21T14:55:39.323 回答