考虑这个interface
public interface IDoSomething {
void DoAAA();
void DoBBB();
void DoCCC();
}
和这两个实现
public class MyObject1 implements IDoSomething {
public MyObject(int a, xObjx x)
..
}
public class MyObject2 implements IDoSomething {
public MyObject(int a, xObjx x)
..
}
我如何不将实现类公开给其他开发人员?具体来说,我该如何防止以下情况?
IDoSomething C = new MyObject2();
使用工厂类是最佳做法吗?
public class DoSomethingFactory {
static IDoSomething getDoSomething(int a, xObjx x) {
...
}
}
如何扩展此模式以包含具有不同构造函数的实现?
答案 0 :(得分:2)
如果您总是要在自己的代码中构建MyObject1 / 2实例,那么您可以将它们打包为私有(默认权限)。 A"建设者"模式也可能有意义。
如果对象的构造函数被暴露,你可以详细说明它是如何/为什么重要的?接口只定义功能要求,而不是构造要求。
答案 1 :(得分:1)
良好的软件是以need to know
为基础编写的。一个组件越无知,关于其伴侣类如何更好地完成工作。这是接口服务的目的。它们允许故意无知的程序员以need to know
为基础编写代码。
一个问题是程序员希望know
几乎总是know
。即使你可以阻止你不能进行的赋值,他们也可以将混淆的对象强制转换为它的实现,用反射检查它的属性和方法,或者将jar传递给十六进制编辑器。这不是你可以阻止的事情。
你可以做的是编写代码,使need to know
程序员的生活更轻松,清楚地传达你的设计意图,并减少程序员作弊的诱惑(使用脏实现细节作为拐杖)。完成此任务的最佳方法是使用Creational Patterns。
关于构造函数不同的观点,这可以通过所有基本的创建模式很好地处理。因为它们提供了构造函数的抽象。您可以决定要公开多少或多少细节。也许你有一个像下面这样的构造函数:
public ColorThing(int r ,int g, int b)
接受数字颜色值。在创建模式的实现中,您可能决定通过构造函数private
来简化它,并且只允许访问静态工厂方法。
private ColorThing(int r , int g, int b){
...
}
public static ColorThing buildRedColorThing(){
return new ColorThing(100,0,0);
}
这会限制您ColorThing
课程的使用者只能构建red
内容。
下面列出了几种基本的创作模式,可以满足您的需求。它们提供了不同程度的混淆,建立到Abstract Factory Pattern
,产生最高程度的封装,但也需要最多的锅炉板。
静态工厂方法
这是上面ColorThing
示例中的人。这只是在类上提供了一个公共静态方法,用于保护构造函数的细节。非常适合简化对包含大量参数的constructor
的访问。在这种情况下,您可以创建构造函数private
并根据需要提供尽可能多的静态工厂方法。
public class MyObject1 implements IDoSomething {
private int prop a;
public static IDoSomething getAnObject(int a){
return new MyObject(a, new xObjx());
}
private MyObject(int a, xObjx x)
...
}
构建器模式
构建器模式有一个附带的类,负责创建您的类。它使用java的范围规则来确保以安全的方式访问构造函数。如果你想拥有大量的telescoping构造函数args,这也非常有用,因为你可以依赖于构建器类的dot chaining
方法(new MyObject1.MyObjectBuilder().setA(2).build()
)
public class MyObject1 implements IDoSomething {
private int prop a;
private MyObject1(int a, xObjx x)
...
public class MyObjectBuilder {
private int a;
public MyObjectBuilder setA(int a){
this.a = a;
return this;
}
public IDoSomething build(){
return new MyObject1(a, new xObjx);
}
}
}
抽象工厂
Abstract Factory Pattern
允许您完全封装类的构造。这只会暴露界面,但它也拥有最多的样板,因为你必须为你想要制造的每个类族创建一个Factory
和一组Product
实现和接口。 Here是该模式中的类如何相关的教科书示例。这种模式是高度可扩展的,你会发现它在很多库代码中都有很好的效果。这是因为这些库的设计者通常不知道他们的框架代码需要支持的全套实现。通过使用Abstract Factory Pattern
,他们可以让未来的开发人员在他们的代码上构建,同时限制他们的假设所施加的限制。
你选择哪一个完全取决于你的情况,但你应该从最简单的一个开始,满足你的需求,并以更复杂的方式工作。