我必须根据特定的情况创建一个对象。我读到过,解决方案可能是工厂模式,但在我的例子中,它有很多缺点。
例如:我有一个管理动物的应用程序。在某个时刻,客户给了我一份必须创建的动物列表。使用工厂模式的解决方案应该是:
//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;
}
}在我看来,这是一种代码气味。问题是我必须写case-statement,以便检查客户想要哪种动物。此外,如果将来我想创建一个新的对象"Tiger",我必须更改所有的工厂类。
我的问题是:有没有办法避免这种情况?有没有一种模式允许我基于另一个参数创建一个对象,而不需要像这样的"cascading if\case-of“?
我在想,使用命令模式,但最后我仍然有这种情况。
发布于 2019-10-26 20:40:14
“代码气味”的概念和它的对立面,“干净的代码”,可以追溯到Martin Fowler和Robert Martin,参见这篇文章,了解olfactory, hygienic和moral simile在软件开发领域的细微差别。
关于这个问题,你认为这种对枚举的切换很糟糕,这与Martin Fowler在"Refactoring: Improving the Design of Existing Code“原版中的观点是一致的,但他在2015 edition中收回了这一观点。在这一点上没有共识,也没有在几个100K声誉贡献者中达成共识,例如@tim-biegeleisen宣布没有臭味,@mark-seemann insists that there is,也是在2015年后,根据他的倾向,只要宇宙存在,就必然如此。
考虑到您对这段特定代码的不满,您可以将实例创建转移到enum本身,从而避免使用switch语句,并避免在扩充Enum时忘记添加额外的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来专门讨论这个问题,作为enum的成员的功能是否会以合理的方式激怒我们的鼻子。
https://stackoverflow.com/questions/58570377
复制相似问题