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

Oop 查找和可能更改方法的最佳设计,oop,Oop,我正在设计一个存储(缓存)一组数据的类。我想查找一个值,如果类包含该值,则使用它并修改该类的属性。我关心公共界面的设计。 下面是如何使用该类: ClassItem *pClassItem = myClass.Lookup(value); if (pClassItem) { // item is found in class so modify and use it pClassItem->SetAttribute(something); ... // use myClass } els

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

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*pClassItem=myClass.Lookup(值); 如果(pClassItem) {//在类中找到项,请修改并使用它 pClassItem->SetAttribute(某物); …//使用myClass } 其他的 {//value在类中不存在,请添加它 添加(价值,某物); } 但是,我不想向这个客户机公开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); } boolfound=myClass.Lookup(值); 如果(找到) {//在类中找到项,请修改并使用它 ModifyAttribute(值,某物); …//使用myClass } 其他的 {//value在类中不存在,请添加它 添加(价值,某物); } 但是,这是低效的,因为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); } boolfound=myClass.LookupAndModify(值,某物); 如果(找到) {//在类中找到了项 …//使用myClass } 其他的 {//value在类中不存在,请添加它 添加(价值,某物); } 但将查找和修改合并为一种方法似乎是非常糟糕的设计。它还仅在找到值时进行修改,因此名称不仅麻烦,而且容易引起误解


有没有其他更好的设计可以绕过这个问题?是否有这种设计模式(我无法通过谷歌找到任何东西)?

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

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

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

这假设您在Modify和Add两种情况下都将值设置为相同的“某物”:

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

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

第一个解决方案是接近

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

然后lookup返回一个索引,modify随后可以使用该索引

void *index = myClass.lookup( value );
if( index ) {
    myClass.modify( index, value );
}
else {
    myClass.add( value );
}
在编写“原语”查找之后,修改并添加,然后编写围绕这些原语构建的自己的复合操作

编写一个LookupAndModify、TryModify、addifynotexists和其他从较低级别的片段构建的方法。

两件事

第一个解决方案是接近

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

然后lookup返回一个索引,modify随后可以使用该索引

void *index = myClass.lookup( value );
if( index ) {
    myClass.modify( index, value );
}
else {
    myClass.add( value );
}
在编写“原语”查找之后,修改并添加,然后编写围绕这些原语构建的自己的复合操作

编写一个LookupAndModify、TryModify、addifynotexists和其他从较低级别的片段构建的方法。

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

您可能正在使用类似的数据结构进行快速查找,因此干净的公共界面(调用站点)将是:

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

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

您可能正在使用类似的数据结构进行快速查找,因此干净的公共界面(调用站点)将是:


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

感谢您的回答。虽然你的名字更好,但我认为TryModify和AddifyNotExists与LookupAndModify有着相同的弱点——他们都在做三件事(lookup,可能是modify,return-found),这对我来说对一个方法来说太多了。这取决于类的语义——我无法从泛型代码示例中辨别出来。设计一个为客户端使用而优化的粗略界面是很好的(在很多情况下甚至更好)。你的类是如何工作的(也许它有3个内部方法)是一个实现细节。谢谢你的回答。虽然你的名字更好,但我认为TryModify和AddifyNotExists与LookupAndModify有着相同的弱点——他们都在做三件事(lookup,可能是modify,return-found),这对我来说对一个方法来说太多了。这取决于类的语义——我无法从泛型代码示例中辨别出来。设计一个为客户端使用而优化的粗略界面是很好的(在很多情况下甚至更好)。您的类如何工作(可能有3个内部方法)是一个实现细节。如果您查看提供的用例,它们最终都会得到相同的结果——对象被修改和存储。那么,为什么(在这个级别上)每次都要让客户端执行这两项检查,从而暴露接口并使其复杂化呢?我假设//使用myClass是一个线索,如果值已经存在,那么会发生一些不同的情况。如果你看一下提供的用例,它们最终都会得到相同的结果——对象被修改和存储。那么,为什么(在这个级别上)每次都要让客户端执行这两项检查,从而使接口暴露和复杂化呢?我假设//使用myClass是一个线索,如果该值已经存在,则会发生一些不同的情况。这是我最初考虑过的,但在发布问题时忘记了。我不太喜欢使用不透明对象,因为类型安全成为一个问题,但我认为只要类是ca