Лучший дизайн для метода поиска и возможного изменения - PullRequest
0 голосов
/ 24 сентября 2008

Я разрабатываю класс, который хранит (кэширует) набор данных. Я хочу посмотреть значение, если класс содержит значение, затем использовать его и изменить свойство класса. Я обеспокоен дизайном общедоступного интерфейса.
Вот как будет использоваться класс:

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 в один метод кажется очень плохим дизайном. Он также изменяется только в том случае, если значение найдено, поэтому имя не только громоздко, но и вводит в заблуждение.

Есть ли другой лучший дизайн, который обходит эту проблему? Какие-нибудь шаблоны дизайна для этого (я не мог найти что-либо через Google)?

Ответы [ 3 ]

2 голосов
/ 26 сентября 2008

На самом деле std::set<>::insert() делает именно это. Если значение существует, оно возвращает итератор, указывающий на существующий элемент. В противном случае возвращается итератор, в который была сделана вставка.

Вполне вероятно, что вы все равно используете похожую структуру данных для быстрого поиска, поэтому чистый публичный интерфейс (вызывающий сайт) будет:

myClass.SetAttribute(value, something)

, который всегда делает правильные вещи. MyClass управляет внутренней сантехникой, и клиенты не беспокоятся о том, существует ли значение.

1 голос
/ 24 сентября 2008

Две вещи.

Первое решение близко.

Не возвращайте ClassItem *. Вернуть «непрозрачный объект». Целочисленный индекс или другой хэш-код, который непрозрачен (не имеет смысла) для клиента, но может использоваться экземпляром myClass.

Затем поиск возвращает индекс, который впоследствии можно использовать для модификации.

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

После написания «примитивного» Lookup, Modify и Add, затем напишите свои собственные составные операции, построенные вокруг этих примитивов.

Напишите LookupAndModify, TryModify, AddIfNotExists и другие методы, построенные из ваших частей более низкого уровня.

1 голос
/ 24 сентября 2008

Предполагается, что вы устанавливаете значение для одного и того же «чего-то» в случаях «Модификация» и «Добавить»:

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

В противном случае:

if (myClass.TryModify(value, something)) {
   // use myClass
} else {
   myClass.Add(value, otherSomething);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...