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

时间:2020-03-06 14:39:32  来源:igfitidea点击:

我正在设计一个用于存储(缓存)一组数据的类。我想查找一个值,如果类包含该值,则使用它并修改该类的属性。我担心公共接口的设计。
这是将如何使用该类的方法:

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); 
}

但是,这样做效率低下,因为"修改"将不得不再次进行查找。这将建议使用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合并为一种方法似乎是非常糟糕的设计。它也只会修改是否找到了值,因此名称不仅麻烦,而且还会引起误解。

是否有另一个更好的设计可以解决此问题?为此有任何设计模式(我无法通过Google找到任何东西)?

解决方案

假设我们在Modify和Add情况下都将值设置为相同的"内容":

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

否则:

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

两件事情。

第一个解决方案即将结束。

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

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

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

编写"原始"查找,修改和添加后,然后编写围绕这些原始构造的自己的复合操作。

编写一个LookupAndModify,TryModify,AddIfNotExists以及从下层代码构建的其他方法。

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

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

myClass.SetAttribute(value, something)

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