【问题标题】:how to avoid "cascading if\case"-statements in a factory class如何避免工厂类中的“级联 if\case”语句
【发布时间】:2019-10-26 11:34:02
【问题描述】:

我必须根据特定情况创建一个对象。我读到,解决方案可能是工厂模式,但就我而言,它有很多缺点。

例如:我有一个管理动物的应用程序。在某个时候,客户给了我必须创建的动物列表。使用工厂模式的解决方案应该是:

//PRODUCTS
public interface  Animal {
    String getCall();
}

public class Dog implements Animal {
    public String getCall() {
        return "Bau";
    }
}

public class Cat implements Animal {
    public String getCall() {
        return "Miao";
    }
}
public class Cow {...}
public class Rooster{...}

public enum AnimalEnum {
    Cat, Dog, Cow, Rooster
}



//FACTORY
public class AnimalFactory {
    public Animal getAnimal (AnimalEnum type){
        Animal retval = null;
        switch (type){
            case Cat:
                retval = new Cat();
                break;
            case Dog:
                retval = new Dog();
                break;
            case Cow:[...]
            case Rooster[...]

        }
        return retval;
    }
}

在我看来,这是一种代码味道。问题是我必须写一个案例陈述来检查客户想要什么类型的动物。 此外,如果将来我想创建一个新对象“Tiger”,我必须更改所有工厂类。

我的问题是:有没有办法避免这种情况?有没有一种模式可以让我基于另一个参数创建一个对象,而不需要像那样的“级联 if\case-of”?

我在想,用命令模式,但最后还是出现这种情况。

【问题讨论】:

  • 这不是代码异味,这就是工厂模式的工作原理。对此的替代方案是,您的其余代码将不得不担心正在使用哪种特定类型的动物,并且这会扩展到比您当前拥有的代码更难维护的代码。

标签: java if-statement switch-statement factory-pattern creation-pattern


【解决方案1】:

“代码异味”的概念及其反义词“干净代码”可以追溯到 Martin Fowler 和 Robert Martin,请参阅这篇文章了解软件开发领域中 olfactory, hygienicmoral simile 的细微差别。

关于这个问题,您认为这种对枚举进行切换的想法与 Martin Fowler 在“Refactoring: Improving the Design of Existing Code”的原始版本中是一致的,但他在2015 edition 中撤回了它。对此没有达成共识,在几个 100K 声誉贡献者之间也没有达成共识,例如@tim-biegeleisen 宣称没有臭味,@mark-seemann insists that there is,也是在 2015 年之后,并且根据他的倾向,只要宇宙存在就必然如此。

由于您对那段特定代码感到不满,您可以将实例创建移至 Enum 本身,从而避免使用 switch 语句,并避免在扩充枚举时忘记添加额外的 switch 分支。

public enum AnimalEnum {
    Cat(Cat::new), 
    Dog(Dog::new), 
    Cow(Cow::new), 
    Rooster(Rooster::new);

    private final Supplier<Animal> createAnimal;

    public Animal createInstance() {
        return createAnimal.get();
    }

    AnimalEnum(Supplier<Animal> factory) {
        this.createAnimal = factory;
    }
}

预计该提案将基于个体嗅觉器官的配置引发争议,并围绕着臭/干净的二分法,我想参考this post,专门讨论这个问题,作为枚举成员的函数是否会激怒我们的鼻子是否合理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多