Wor*_*tig 6 java enums extensibility design-patterns software-quality
我试图让我的代码更容易扩展,因为一点点的改变不会影响其他代码。
我有一个enum MyEnum,其值将来可能会增加。
然后,有一些类保存它的实例,并且许多行为受到该enum的具体值的影响。换句话说,有很多地方我切换了它的值。
public enum MyEnum
{
FIRST, SECOND, THIRD, FOURTH;
}
public class A
{
private MyEnum myEnum
public A(MyEnum myEnum)
{
this.myEnum = myEnum;
}
// as you will see, there is a lot of switching over its value
public void boo()
{
switch(myEnum)
{
case FIRST: // do smtng
case SECOND: // do smthing else
case THIRD: // do smthing else
case FOURTH: // do nice thing
}
}
public int goo()
{
switch(myEnum)
{
...
}
}
public AnotherObject foo()
{
switch(myEnum)
{
...
}
}
}
public class B
{
private MyEnum myEnum
public B(MyEnum myEnum)
{
this.myEnum = myEnum;
}
public double doo()
{
switch(myEnum)
{
...
}
}
public void soo()
{
switch(myEnum)
{
...
}
}
public boolean xoo()
{
switch(myEnum)
{
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,大多数情况下,我需要将新的情况添加到我们切换其值的所有位置=>当我添加新的枚举值时,需要对代码进行许多更改。
还有其他人遇到过这个问题吗?到目前为止,我想这只是以这种方式使用enum的缺点。
不要将您的代码绑定enum到接口。然后让您的枚举提供接口的标准实现。
public interface RibbonColor {
public String getColor();
}
public enum DefaultRibbonColors implements RibbonColor {
FIRST() {
public String getColor() {
return "blue";
}
},
SECOND() {
public String getColor() {
return "red";
}
},
THIRD() {
public String getColor() {
return "white";
}
},
}
public class Awards {
private List<RibbonColor> ribbons;
public Awards(List<RibbonColor> ribbons) {
this.ribbons = ribbons;
}
public RibbonColor awardFor(int placeIndex) {
if (placeIndex < ribbons.length()) {
return ribbons.get(placeIndex).getColor();
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,现在您可以轻松添加所有默认值的新Awards列表
Awards awards = new Awards(Arrays.asList(DefaultRibbonColors.values()));
Run Code Online (Sandbox Code Playgroud)
同时您还可以创建自定义奖励集。
List ribbons = new ArrayList<RibbonColor>();
ribbons.addAll(DefaultRibbonColors.values());
ribbons.addAll(ExtendedRibbonColors.values());
ribbons.addAll(new BlackAndPinkPolkaDotRibbonColor());
Awards awards = new Awards(ribbons);
Run Code Online (Sandbox Code Playgroud)
关键是永远不要让代码实际上依赖于,enum因为如果不enum重新编译就无法修改,并且这会触发需要搜索switch缺少的语句default:块或更明确的附加值设置的语句。
对象是“一起编写的代码和数据”,而过程代码是“代码和数据分开管理”。该switch语句将逻辑“代码”置于类型“数据”之外,并且是 100% 疯狂的面向对象设计中的编程错误。也就是说,它通常是有用的,人们仍然以有效地将代码与数据(保存所有数据的对象,以及操作另一个对象的数据的“对象例程”)分离的方式用 Java 和其他语言构建程序。来自其例程的对象数据是一种反模式,称为anemic objects。
Enums所以Objects不要害怕在其中添加方法!为它们提供可复制的接口,并避免使用 switch 语句,因为这可能是一个好兆头,表明逻辑应该位于您要打开的事物中(前提是它是一个对象)。