查找和可能更改方法的最佳设计

时间:2008-09-24 12:35:38

标签: oop

我正在设计一个存储(缓存)一组数据的类。我想查找一个值,如果该类包含该值,则使用它并修改该类的属性。我关心公共界面的设计 以下是该课程的使用方法:

ClassItem *pClassItem = myClass.Lookup(value);
if (pClassItem)
{ // item is found in class so modify and use it 
  pClassItem->SetAttribute(something);
  ... // use myClass
}
else
{  // value doesn't exist in the class so add it
  myClass.Add(value, something); 
}

但是我不想将ClassItem暴露给这个客户端(ClassItem是MyClass的一个实现细节)。 为了解决这个问题,可以考虑以下几点:

bool found = myClass.Lookup(value);
if (found)
{ // item is found in class so modify and use it 
  myClass.ModifyAttribute(value, something);
  ... // use myClass
}
else
{  // value doesn't exist in the class so add it
  myClass.Add(value, something); 
}

然而,这是低效的,因为Modify必须再次进行查找。这将建议使用lookupAndModify类型的方法:

bool found = myClass.LookupAndModify(value, something);
if (found)
{ // item is found in class
  ... // use myClass
}
else
{  // value doesn't exist in the class so add it
  myClass.Add(value, something); 
}

但将LookupAndModify滚动到一个方法似乎非常糟糕的设计。它也只会修改是否找到值,因此名称不仅繁琐,而且具有误导性。

还有另一个更好的设计可以解决这个问题吗?任何设计模式(我通过谷歌找不到任何东西)?

3 个答案:

答案 0 :(得分:2)

实际上std::set<>::insert()正是这样做的。如果值存在,则返回指向现有项的迭代器。否则,返回插入的迭代器。

无论如何,您可能正在使用类似的数据结构进行快速查找,因此一个干净的公共接口(调用站点)将是:

myClass.SetAttribute(value, something)

总是做正确的事。 MyClass处理内部管道,客户端不担心值是否存在。

答案 1 :(得分:1)

这假设您在“修改”和“添加”案例中将值设置为相同的“某事”:

if (!myClass.AddIfNotExists(value, something)) {
   // use myClass
}

否则:

if (myClass.TryModify(value, something)) {
   // use myClass
} else {
   myClass.Add(value, otherSomething);
}

答案 2 :(得分:1)

两件事。

第一个解决方案已经结束。

但是,请不要返回ClassItem *。返回“不透明对象”。对客户端不透明(无意义)但可由myClass实例使用的整数索引或其他哈希代码。

然后查找返回一个索引,修改后可以使用该索引。

void *index = myClass.lookup( value );
if( index ) {
    myClass.modify( index, value );
}
else {
    myClass.add( value );
}

在编写“原始”查找,修改和添加之后,编写围绕这些原语构建的自己的复合操作。

编写LookupAndModify,TryModify,AddIfNotExists以及从较低级别构建的其他方法。