静态方法M
返回实现接口A
的对象:
interface A { ... }
static A M() { ... }
在M
内我想构建一个B
类型的对象并返回该对象,假设B
实现了A
:
class B implements A { ... }
我不希望客户端代码知道有关B
如何实现的任何内容,我希望首选 B
不要成为static
类,{ {1}} 必须是不可变的,并且可能会有不同的B
传递给不同的客户端。我想不惜一切代价阻止B
方法B
的实例化(没有反思,正如一位用户所评论的那样)。
我如何实现上述目标?我应该在哪里以及如何实施M
?你能提供一个简短的代码示例吗?
我的主要问题是:我怎么能有“不同B
s?”
答案 0 :(得分:4)
静态内部类可能是你最好的选择。您将无法“不惜一切代价阻止B
实例化”,因为通过反射,客户端代码可以绕过所有访问修饰符。
答案 1 :(得分:3)
您可以使用不会被称为B(匿名)的匿名内部类,但会实现A
,例如
interface A {
void someMethod();
}
public class Test {
static A M() {
return new A() {// it will create and return object of anonymous
// class that implements A
@Override
public void someMethod() {
}
};
}
}
不使用匿名类的反射对象只能通过方法M
创建。它也不能扩展,因此它是不可变性的良好第一步。
答案 2 :(得分:0)
您还可以使用Proxy
实现来进一步隐藏实现类
public interface A {
public Object getValue();
}
public class Factory {
public static A newInstance() {
return new ProxyA(AImpl);
}
}
public class ProxyA implements A {
private A proxy;
public ProxyA(A proxy) {
this.proxy = proxy;
}
public Object getValue() {
return proxy.getValue();
}
}
所有这一切实际上都是将A
的实现隐藏在另一个布局下,并且难以创建ProxyA
的实例
但正如@Asaph指出的那样,通过反思,几乎不可能真正防止人们访问类和对象的各个部分......
您还可以通过不同的Classloaders
分离您的接口和实现,这样您只需将接口公开给开发人员,并通过动态类在运行时加载它们来实现。虽然没有解决潜在的问题,但它会使那些试图规避工厂的人更加复杂化。
IMHO