使用每个子类方法创建工厂对象
factory object creation using per-subclass method
我有一个简单的工厂 (GenericFudge),它根据外部环境创建不同类型的对象。目前,我的代码看起来像这样:
abstract class Fudge {
Fudge() {
}
void make() {
System.out.println("made.");
}
}
class VanillaFudge extends Fudge {
@Override
void make() {
System.out.print("Vanilla ");
super.make();
}
}
class ChocolateFudge extends Fudge {
@Override
void make() {
System.out.print("Chocolate ");
super.make();
}
}
class InvalidFlavorException extends Exception {};
// factory / proxy
public class GenericFudge {
Fudge mFudge = null;
GenericFudge(String flavor) throws InvalidFlavorException {
if (flavor.equals("Chocolate")) {
mFudge = new ChocolateFudge();
} else if (flavor.equals("Vanilla")) {
mFudge = new VanillaFudge();
}
}
void make() {
mFudge.make();
}
public static void main(String args[]) {
for (String flavor : new String[] {"Chocolate", "Vanilla"}) {
GenericFudge fudge;
try {
fudge = new GenericFudge(flavor);
fudge.make();
} catch (InvalidFlavorException e) {
System.out.println("Sorry, we don't make that flavor");
}
}
}
}
我的目标是从 GenericFudge 中获取巧克力和香草的细节,以便在实现 CaramelFudge 时,不需要对 GenericFudge 进行任何更改。例如,GenericFudge 会为每个 xxxFudge class 迭代调用一个 "createIfItsMyFlavor()" 方法。 (在我的实际应用中,我必须反复尝试它们,但我会对其他可能性感兴趣。)
我的直觉是为每个子class(每个xxxFudge)使用一个静态初始化程序,它通过调用GenericFudge 的registerFudge 方法将"itself" 添加到列表中,但这会遇到问题egg 问题(class 从未使用过,因此它的静态初始值设定项永远不会被调用)。
毫无疑问,还有一种我没有想到的更好的方法。谢谢!
如果您使用任何类型的依赖注入系统,如 Spring,使用 @PostConstruct 很容易实现。如果这有效,那么您可以从使用 PostConstruct 注释的方法调用 GenericFudge 中的注册方法。在 GenericFudge 中,您有一个地图,每当调用 addType 时,您就将其添加到地图中。这样你的 GenericFudge 保持不变,新的调用者将使用 PostConstruct 注册。为了进一步简化事情,您可以在您的基础 class Fudge 中定义它,并使用构造函数传递 fudge 名称,这样您就不必在每个子 class 中声明 register 方法。
private String fudge;
public Fudge(final String fudge) {
this.fudge = fudge;
}
@Autowired
private GenericFudge fudge;
@PostConstruct
private void register() {
fudge.addType(fudge, this);
}
在 GenericFudge 中
private Map<String, Fudge> fudgeTypes = Maps.newHashMap();
public void register(final String fudgeType, final Fudge fudgeInstance) {
fudgeTypes.put(fudgeType, fudgeInstance);
}
如果您不使用任何依赖注入系统:
另一种方法可能是在基础 class Fudge 中使用静态方法,您可以在其中声明所有类型的软糖,然后 return 根据请求创建一个实例。这样您就不会修改 GenericFudge class,而只会修改 Fudge 的基础 class。这并不理想,但它使您不必修改 GenericFudge class,而不是 "registering" 使用类似 PostConstruct 的东西,您可以在 Map 中添加一个条目。
示例(来自 Guava 的 ImmutableMap,您可以根据需要声明地图,这仅用于示例):
public abstract class Fudge {
private static final Map<String, Fudge> FUDGE_TYPES = ImmutableMap.of(
"Type1", new Type1Fudge(),
"Type2", new Type2Fudge()
// Add new entry when implemented
);
public static Fudge getFudge(final String fudge) {
if (FUDGE_TYPES.containsKey(fudge)) {
return FUDGE_TYPES.get(fudge);
} else {
// handle missing fudge depending on your preference
}
}
}
我有一个简单的工厂 (GenericFudge),它根据外部环境创建不同类型的对象。目前,我的代码看起来像这样:
abstract class Fudge {
Fudge() {
}
void make() {
System.out.println("made.");
}
}
class VanillaFudge extends Fudge {
@Override
void make() {
System.out.print("Vanilla ");
super.make();
}
}
class ChocolateFudge extends Fudge {
@Override
void make() {
System.out.print("Chocolate ");
super.make();
}
}
class InvalidFlavorException extends Exception {};
// factory / proxy
public class GenericFudge {
Fudge mFudge = null;
GenericFudge(String flavor) throws InvalidFlavorException {
if (flavor.equals("Chocolate")) {
mFudge = new ChocolateFudge();
} else if (flavor.equals("Vanilla")) {
mFudge = new VanillaFudge();
}
}
void make() {
mFudge.make();
}
public static void main(String args[]) {
for (String flavor : new String[] {"Chocolate", "Vanilla"}) {
GenericFudge fudge;
try {
fudge = new GenericFudge(flavor);
fudge.make();
} catch (InvalidFlavorException e) {
System.out.println("Sorry, we don't make that flavor");
}
}
}
}
我的目标是从 GenericFudge 中获取巧克力和香草的细节,以便在实现 CaramelFudge 时,不需要对 GenericFudge 进行任何更改。例如,GenericFudge 会为每个 xxxFudge class 迭代调用一个 "createIfItsMyFlavor()" 方法。 (在我的实际应用中,我必须反复尝试它们,但我会对其他可能性感兴趣。)
我的直觉是为每个子class(每个xxxFudge)使用一个静态初始化程序,它通过调用GenericFudge 的registerFudge 方法将"itself" 添加到列表中,但这会遇到问题egg 问题(class 从未使用过,因此它的静态初始值设定项永远不会被调用)。
毫无疑问,还有一种我没有想到的更好的方法。谢谢!
如果您使用任何类型的依赖注入系统,如 Spring,使用 @PostConstruct 很容易实现。如果这有效,那么您可以从使用 PostConstruct 注释的方法调用 GenericFudge 中的注册方法。在 GenericFudge 中,您有一个地图,每当调用 addType 时,您就将其添加到地图中。这样你的 GenericFudge 保持不变,新的调用者将使用 PostConstruct 注册。为了进一步简化事情,您可以在您的基础 class Fudge 中定义它,并使用构造函数传递 fudge 名称,这样您就不必在每个子 class 中声明 register 方法。
private String fudge;
public Fudge(final String fudge) {
this.fudge = fudge;
}
@Autowired
private GenericFudge fudge;
@PostConstruct
private void register() {
fudge.addType(fudge, this);
}
在 GenericFudge 中
private Map<String, Fudge> fudgeTypes = Maps.newHashMap();
public void register(final String fudgeType, final Fudge fudgeInstance) {
fudgeTypes.put(fudgeType, fudgeInstance);
}
如果您不使用任何依赖注入系统: 另一种方法可能是在基础 class Fudge 中使用静态方法,您可以在其中声明所有类型的软糖,然后 return 根据请求创建一个实例。这样您就不会修改 GenericFudge class,而只会修改 Fudge 的基础 class。这并不理想,但它使您不必修改 GenericFudge class,而不是 "registering" 使用类似 PostConstruct 的东西,您可以在 Map 中添加一个条目。
示例(来自 Guava 的 ImmutableMap,您可以根据需要声明地图,这仅用于示例):
public abstract class Fudge {
private static final Map<String, Fudge> FUDGE_TYPES = ImmutableMap.of(
"Type1", new Type1Fudge(),
"Type2", new Type2Fudge()
// Add new entry when implemented
);
public static Fudge getFudge(final String fudge) {
if (FUDGE_TYPES.containsKey(fudge)) {
return FUDGE_TYPES.get(fudge);
} else {
// handle missing fudge depending on your preference
}
}
}