首先,我没有理由不允许直接实例化你的类。通常,你不关心谁实例化了这个类,只要你确定它实例化了就可以。
因此,我相信你有没有一个问题,而是两个:
- 为人提供一种方法来正确地创建这两个手动,如果需要的话类
A
和类B
。
- 提供一种实例化给定一组抽象参数(工厂解决方案)的
A
或B
的方法。
对于第一部分,3种方法来正确地实例化不同复杂性的类:
- 构造函数,它具有所有必需的参数和依赖关系的列表。这可以用于很简单的情况。
- 工厂方法。这可以用于更复杂的场景。
- 工厂类/构建器类。这些通常用于复杂场景。
现在,无论您选择哪一个,都应该允许所有逻辑公开。构造函数/工厂方法/工厂类将强制您的规则创建A
或B
的适当有效实例。而且,正如我之前提到的,当你不应该创建一个完美的,有效的类的实例时,没有可能的情况。
假设您将建造者类作为最复杂的解决方案。这里是你的代码的外观:
package com.app.letter.A;
public class A {
A() { //Package visibility, we don't want anyone to create an invalid A class
...
}
...
}
public class ABuilder {
public void validateAndSetSomeCriticalParam(Param param) {
...
}
public A build() {
A a = new A();
a.setSomeCriticalParam(param);
...
return a;
}
}
建设者应该在心中的思想进行设计,它不能以任何方式产生的A
无效的实例。这样,您可以允许构建器成为实例化A
而不必担心的唯一方式,因为它创建的所有实例始终有效。您可以在构建器上使用适当的API或例外来达到此目的。 另外,构建器方法是最复杂的方法,对于一些更简单的场景,您可能会使用一些公共静态工厂方法。但是这个想法应该保持不变 - 公共工厂方法应该确保它们只生成A
的有效实例。
为B级同样的东西,在其他包:
package com.app.letter.B;
public class B {
...
}
public class BBuilder {
...
}
现在的工厂。基本上同样的事情,你有,但建设者:
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
if (doesNotMatter.isA()) {
ABuilder builder = new ABuilder();
builder.setSomeCriticalParam(...);
builder...
return builder.build();
} else {
BBuilder builder = new BBuilder();
builder.setSomeBSpecificParam(...);
builder...
return builder.build();
}
}
}
约在用法:
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(..whatever..); // Legal
new A(); //Illegal, as it is package protected
new B(); //Illegal, as it is package protected
new ABuilder(); //Legal, as ABuilder can ensure that only valid As are created
new BBuilder(); //Legal, as BBuilder can ensure that only valid Bs are created
}
}
我会添加,再次重复自己,你应该只隐藏你的系统的部分,可以是在某些方面受到虐待。如果没有办法让它被滥用,那么就没有必要隐藏一个类或一个方法。因此,如果您提供了正确初始化A
或B
的有效实例的方法,则系统的其他某个部分可以看到它或使用它并不重要。
有趣的是,您担心在同一个包中执行非法事件的类。它在某些方面类似于访问类的私有成员的类中的代码,而不是通过公共方法。通常我们隐藏了一些东西,因为如果我们改变它们,我们不希望代码破坏。您是否希望包中的开发人员在不知道风险的情况下访问A和B?另外,我认为如果该功能使用Java 9中的模块,则可以使用Java 9中的Module执行此操作。 – Fuhrmanator