gpt4 book ai didi

java - 如果在验证规则中使用类型代码,如何进行重构以消除类型代码?

转载 作者:行者123 更新时间:2023-12-02 05:01:52 25 4
gpt4 key购买 nike

假设我们在向集合中添加新元素之前必须检查一组规则。元素是一些相似类型的对象。所有类型特定的功能都封装在抽象类的子类中。集合包含此抽象类的对象。这些规则适用于类型的条件以及其他约束。因此,项目的抽象父类(super class)具有附加的类型代码。可以将新元素添加到集合中,但由于附加规则,可以删除或替换集合中的其他元素。

在需要重构的代码中,规则的验证被实现为带有嵌套控制流语句的一长段代码。类型代码的验证会破坏封装。控制流语句的单独分支不能定义为集合元素相应子类的方法,因为它们需要检查类型并对集合进行更改。

关于我的案例中的类型代码的其他事实:

  • 类型代码不会影响类的行为
  • 类型代码是不可变的
  • 类型代码被 ItemsManager 用于在添加之前解析一些规则集合中的新元素。

如何消除类型代码并将规则与类型分开?

以下是此类问题的示例:

Items 的类型特定功能封装在 AbstractItem 子类中。
ItemManager 类的 add 方法破坏了封装。
规则:如果 Type1 的新项具有相同的 SomeUsefull 属性值,则必须删除 Type2 的项正在添加到集合中。

为了简单起见,省略了 ICloneable 和 IComparable 接口(interface)的实现。在现实世界中,集合中的项目是不可变和可克隆的,并且规则系统非常复杂。

abstract class AbstractItem {

private int Type; // this would like to eliminate
private int SomeUseful;

protected AbstractItem(int Type, int Value) {
this.Type = Type;
this.SomeUseful = Value;
}

public int getType() { return this.Type; }
public int getSomeUseful() { return this.SomeUseful; }

@Override
public String toString() {
return String.format("Item{Type=%d, Value=%d}", Type, SomeUseful);
}
}

class ItemType1 extends AbstractItem {
ItemType1(int Value) { super(1, Value); }
}

class ItemType2 extends AbstractItem {
ItemType2(int Value) { super(2, Value); }
}

class ItemManager {

private java.util.ArrayList<AbstractItem> ListOfItems;

public ItemManager(){
this.ListOfItems = new java.util.ArrayList<AbstractItem>();
}

public void add(final AbstractItem newItem) {
// this code breaks encapsulation
switch (newItem.getType()) {
case 1:
// do some type dependent operations
for(AbstractItem i: this.ListOfItems) {
if (i.getType()==2 && i.getSomeUseful()==newItem.getSomeUseful()) {
this.ListOfItems.remove(i);
break;
}
}
break;
case 2:
// do some other type dependent operations
break;
default:
// throw error
}
this.ListOfItems.add(newItem);
}

@Override
public String toString() {
String str = String.format("ItemsManager content");
for(AbstractItem i: this.ListOfItems) {
str += String.format("\n\tType = %d, Value = %d", i.getType(), i.getSomeUseful());
}
return str;
}
}

public class Example1 {
public static void main(String[] arg) {
System.out.println("Example 1");
ItemManager im = new ItemManager();
im.add(new ItemType1(1));
im.add(new ItemType2(2));
im.add(new ItemType2(3));
im.add(new ItemType1(3));
System.out.println(im.toString());
}
}

/*
Example 1
ItemsManager content
Type = 1, Value = 1
Type = 2, Value = 2
Type = 1, Value = 3
*/

最佳答案

从@dbugger的答案开始,你可以进一步插入它。您可以使用双重调度来隐藏类型代码。仍然不是一个完美的解决方案,因为父级对其子级了解太多,但类型代码现在已经消失了。

很难用您给出的示例代码来判断什么是更好的解决方案,因为当您简化时,您删除了有关所涉及项目的所有信息。那里可能有一些东西可以以其他方式用于区分,允许您使用 shoudBeRemovedBecauseType1 摆脱双重调度。

这是对类型 1 进行修改的 onAdd 方法

@Override
public List<AbstractItem> onAdd(List<AbstractItem> list) {
for (AbstractItem item : list) {
if (item.shoudBeRemovedBecauseType1(this)) {
list.remove(item);
break;
}
}
return list;
}

基类中的新方法

    public boolean shoudBeRemovedBecauseType1(ItemType1 itemType1)
{
return false;
}

在类型 2 子类中重写

    @Override
public boolean shoudBeRemovedBecauseType1(ItemType1 itemType1)
{
return getSomeUseful() == itemType1.getSomeUseful();
}

关于java - 如果在验证规则中使用类型代码,如何进行重构以消除类型代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28204492/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com