[英]The best way to implement Factory without if, switch
我正在研究用Java實現Factory模式的許多方法,但仍然找不到一個完美的方法,如果/ switch plus不使用反射,則不會受到影響。 我找到的最好的一個是Tom Hawtin在這里的答案: https : //stackoverflow.com/a/3434505/1390874
但我最擔心的是它將匿名類的HashMap存儲在內存中。
問題是除了Tom Hawtin的答案之外,人們還會考慮使用Class.newInstance()嗎? 這樣可以避免我們在內存中存儲不必要的匿名類嗎? 加上代碼會更干凈。
它看起來像這樣:
class MyFactory {
private static final Map<String,Class> factoryMap =
Collections.unmodifiableMap(new HashMap<String,Class>() {{
put("Meow", Cat.class);
put("Woof", Dog.class);
}});
public Animal createAnimal(String action) {
return (Animal) factoryMap.get(action).newInstance();
}
}
如果您使用的是java 8,則可以設置如下的enum
:
enum AnimalFarm {
Meow(Cat::new),
Woof(Dog::new);
public final Supplier<Animal> factory;
private AnimalFarm(Supplier<Animal> factory) {
this.factory = requireNonNull(factory);
}
}
......
Animal dog = AnimalFarm.valueOf("Woof").factory.get();
您甚至可以使enum
實現Supplier<Animal>
,然后執行AnimalFarm.valueOf("Meow").get();
。
嘗試這樣的事情:
class MyFactory {
private static final Map<String,Animal<?>> factoryMap =
Collections.unmodifiableMap(new HashMap<String,Class>() {
put("Meow", Cat.BASE_INSTANCE);
put("Woof", Dog.BASE_INSTANCE);
});
public Animal createAnimal(String action) {
return factoryMap.get(action).instance();
}
}
interface Animal<SELF> {
public SELF instance();
}
class Cat implements Animal<Cat> {
public static final Cat BASE_INSTANCE = new Cat();
public Cat() {}
public Cat instance(){
return new Cat();
}
}
// And a similar Dog class
這根本不使用反射, if
或者switch
。
Java 8引入了一些很好的lambdas和功能接口,這使得這非常簡單。 它還避免了您在以前的Java版本中必須編寫的許多丑陋的樣板代碼。 有一件事並不是很清楚,那就是如何使用帶有多個參數的構造函數來處理創建對象。 大多數Java的功能接口允許一個參數或根本不允許任何參數。 在這種情況下,解決方案是實現您自己的功能接口。
想象一下,你的Animal類都有如下所示的構造函數:
public Dog(String name, int age) {
// constructor stuff
}
您可以在工廠類中創建一個名為Factory
的函數接口,該接口具有3個參數。 前兩個參數是您要傳遞給構造函數的對象類型,第三個參數將是您要返回的對象。
public class AnimalFactory {
private static final Map<String, Factory<String, Animal>> factoryMap;
static {
Map<String, Factory<String, Animal>> realMap = new HashMap<>();
factoryMap = Collections.unmodifiableMap(realMap);
realMap.put("MEOW", Cat::new);
realMap.put("WOOF", Dog::new);
}
public static Animal createAnimal(String action) {
return factoryMap.get(action).create(node);
}
@FunctionalInterface
private interface Factory<T, R, S> {
S create(T obj1, R obj2);
}
}
如果所有類都使用no-arg構造函數,那么您可以刪除自定義接口並使用類似於Supplier
東西。 但其他一切應該或多或少保持不變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.