簡體   English   中英

沒有if,切換實現Factory的最佳方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM