Java +Strategy + Factory + same package =如何隐藏特化类?
Java +Strategy + Factory + same package = how to hide specialized classes?
我想对同一个包的外部 classes 隐藏特化 classes。
示例:
package com.app.letter;
public interface LetterChange {
void change();
}
public class A implements LetterChange{
public void change(){..}
}
public class B implements LetterChange{
public void change(){..}
}
为了实例化这些 classes,我使用了一个工厂....
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
注意,它们都在同一个包中,我不想将工厂和专门的 classes 放在子包中并更改专门化 classes 的默认构造函数(包)。
按照这个例子,我在同一个包中有第三个 class
package com.app.letter;
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(null); // Legal
new A(); Illegal
new B(); Illegal
}
}
我只想由工厂提供 A 或 B LetterFactory.getInstance(doesNotMatter),它们在同一个包装中。
您可以通过将 A 和 B 设为包保护来从其他包中隐藏它们。
但这不会在同一个包中对 classes 隐藏它们。
由于它们必须对工厂可见,但对同一包的任何其他 class 不可见,唯一的方法是将它们设为 private static 嵌套 classes工厂 class.
使工厂的 A
和 B
私有静态 类:
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
private static class A implements LetterChange{
public void change(){..}
}
private static class B implements LetterChange{
public void change(){..}
}
}
只有工厂知道这些 类 的存在并且可以实例化它们。
首先,我认为没有理由不允许直接实例化您的 classes。通常,您不关心谁实例化了 class,只要您确定它实例化 正确 即可。
因此,我相信你的问题不是一个,而是两个:
- 为 任何人 提供一种方法,以便在需要时手动正确创建 class
A
和 class B
。
- 提供一种在给定一组抽象参数(您的工厂解决方案)的情况下实例化
A
或 B
的方法。
至于第一部分,有 3 种方法可以正确实例化 class 不同复杂度的实体:
- 一个构造函数,其中包含所有必需参数和依赖项的列表。这可以很好地用于简单的情况。
- 一个工厂方法。这可以用于更复杂的场景。
- 工厂 class/a 建造者 class。这些通常用于复杂的场景。
现在,无论您选择哪个,按照所有逻辑都应该被允许 public。 constructor/factory method/factory class 将执行您的规则以创建 A
或 B
的适当有效实例。而且,正如我之前提到的,当您不允许创建 class.
的完美且有效的实例时,没有任何可能的情况。
假设您使用构建器 class 作为最复杂的解决方案。您的代码可能如下所示:
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 来实现这一点。
此外,构建器方法是最复杂的方法,对于一些更简单的场景,您可能会使用一堆 public 静态工厂方法。然而,想法应该保持不变 - public 工厂方法应该确保它们只生成 A
.
的有效实例
B class 的相同内容,在其他包中:
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
}
}
我要补充一点,再次重申,您应该只隐藏系统中可能会以某些方式被滥用的部分。如果无法滥用 class 或方法,则没有必要隐藏它。因此,如果您提供了一种方法来正确初始化 A
或 B
的有效实例,那么系统的其他部分可以看到或使用它对您来说应该无关紧要。
我想对同一个包的外部 classes 隐藏特化 classes。
示例:
package com.app.letter;
public interface LetterChange {
void change();
}
public class A implements LetterChange{
public void change(){..}
}
public class B implements LetterChange{
public void change(){..}
}
为了实例化这些 classes,我使用了一个工厂....
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
注意,它们都在同一个包中,我不想将工厂和专门的 classes 放在子包中并更改专门化 classes 的默认构造函数(包)。
按照这个例子,我在同一个包中有第三个 class
package com.app.letter;
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(null); // Legal
new A(); Illegal
new B(); Illegal
}
}
我只想由工厂提供 A 或 B LetterFactory.getInstance(doesNotMatter),它们在同一个包装中。
您可以通过将 A 和 B 设为包保护来从其他包中隐藏它们。
但这不会在同一个包中对 classes 隐藏它们。
由于它们必须对工厂可见,但对同一包的任何其他 class 不可见,唯一的方法是将它们设为 private static 嵌套 classes工厂 class.
使工厂的 A
和 B
私有静态 类:
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
private static class A implements LetterChange{
public void change(){..}
}
private static class B implements LetterChange{
public void change(){..}
}
}
只有工厂知道这些 类 的存在并且可以实例化它们。
首先,我认为没有理由不允许直接实例化您的 classes。通常,您不关心谁实例化了 class,只要您确定它实例化 正确 即可。
因此,我相信你的问题不是一个,而是两个:
- 为 任何人 提供一种方法,以便在需要时手动正确创建 class
A
和 classB
。 - 提供一种在给定一组抽象参数(您的工厂解决方案)的情况下实例化
A
或B
的方法。
至于第一部分,有 3 种方法可以正确实例化 class 不同复杂度的实体:
- 一个构造函数,其中包含所有必需参数和依赖项的列表。这可以很好地用于简单的情况。
- 一个工厂方法。这可以用于更复杂的场景。
- 工厂 class/a 建造者 class。这些通常用于复杂的场景。
现在,无论您选择哪个,按照所有逻辑都应该被允许 public。 constructor/factory method/factory class 将执行您的规则以创建 A
或 B
的适当有效实例。而且,正如我之前提到的,当您不允许创建 class.
假设您使用构建器 class 作为最复杂的解决方案。您的代码可能如下所示:
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 来实现这一点。
此外,构建器方法是最复杂的方法,对于一些更简单的场景,您可能会使用一堆 public 静态工厂方法。然而,想法应该保持不变 - public 工厂方法应该确保它们只生成 A
.
B class 的相同内容,在其他包中:
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
}
}
我要补充一点,再次重申,您应该只隐藏系统中可能会以某些方式被滥用的部分。如果无法滥用 class 或方法,则没有必要隐藏它。因此,如果您提供了一种方法来正确初始化 A
或 B
的有效实例,那么系统的其他部分可以看到或使用它对您来说应该无关紧要。