3

静态方法M返回一个对象实现接口A

interface A { ... }
static A M() { ... }

M我想构造一个类型的对象B并返回它,给定B实现A

class B implements A { ... }

我不希望客户端代码知道有关如何B实现的任何信息,我宁愿B不成为一个类staticB 必须是不可变的,并且可以不同的方式B交给不同的客户端。我想不惜一切代价阻止B外部方法的实例化M(正如一位用户评论的那样,缺少反射)。

我怎样才能实现上述目标?我应该在哪里以及如何实施B?您能否提供一个简短的代码示例?

我的主要问题是:我怎样才能拥有“不同B的 s”?

4

3 回答 3

4

静态内部类可能是您最好的选择。您将无法“B不惜一切代价阻止实例化”,因为通过反射,客户端代码可以绕过所有访问修饰符。

于 2012-08-04T23:10:43.277 回答
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。它也不能扩展,所以它是不变性的第一步。

于 2012-08-04T23:13:33.993 回答
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,这样您就只向开发人员公开接口,并且实现是通过在运行时加载它们的动态类来交付的。虽然没有解决根本问题,但对于那些试图绕过你的工厂的人来说,它使事情变得更加复杂。

恕我直言

于 2012-08-04T23:22:14.507 回答