Шаблон проектирования для использования, когда приложение хочет знать, какой конкретный класс оно получило - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть структура класса, подобная приведенной ниже.

    class Technology;
    class BasicTechnology : public Technology;
    class BasicChildTechnology : public BasicTechnology;
    class ConcreteChildTechnology1 : public BasicChildTechnology;//concretechildtech1
    class ConcreteChildTechnology2 : public BasicChildTechnology;//concretechildtech2
    class ConcreteChildTechnology3 : public BasicChildTechnology;//concretechildtech3
...
    class ConcreteChildTechnologyN : public BasicChildTechnology;//concretechildtechN

В ConcreteChildTechnologyN/3/2/1 есть метод isValid(String selector), как показано ниже,

public isValid(String selector){
 return "concretechildtech1".Equals(selector);
}

Сейчас вкод клиента:

Technology tech = getTechnologyObject("concretechildtech1"); //tech becomes an instance of ConcreteChildTechnology1

Как мне реализовать getTechnologyObject() в этом случае ?.

Мысль об использовании абстрактного фабричного паттерна, но сомнительная в этом.или даже создать Facade и создать конкретный дочерний элемент на основе входного аргумента?Проблема в том, что только ConcreteChildTechnology1 знает, принадлежит ли ему входная строка (concretechildtech1) или нет;через isValid() метод.

Опять же, если я начну каждый раз создавать N объектов для проверки достоверности, это вызовет и накладные расходы, потому что 1) система работает в среде с очень низким объемом памяти, такой как мобильные телефоны и планшеты, 2) число созданных экземпляров велико, 10-100 в минуту.

Может быть сделать isValid() статическим встроенным методом и создать объект на основе ответа от дочерних объектов?

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Насколько я понимаю, getTechnologyObject("string") возвращает интеллектуальную ссылку / указатель типа std::shared_ptr<BasicChildTechnology> на основе строки.Внутри этой функции есть список этих технических объектов, и только этот технический объект знает, связан ли он с этой строкой.

Первая проблема - эта строка.Возможно ли преобразовать его в перечисление или какой-то более точный тип данных раньше, чем сейчас?Уже одно это сделает вашу систему более надежной и быстрой.

Вторая проблема - это владение критериями соответствия.Я представляю, когда система разрабатывалась, это казалось естественным.Я хотел бы отметить, что этот объект не несет единой ответственности.И то, и другое должно быть выполнено независимо от того, что это за технология, и должно совпадать с каким-либо форматом сериализации.Возможно, все еще имеет смысл оставить строку внутри этого объекта (это может быть имя), но сопоставление должно быть поднято за пределы объекта и в функцию поиска getTechnologyObject("string").

Теперь независимо от того,у вас есть строка / число, техническим объектам нужна функция virtual label_t label() (назовите ее по своему усмотрению), которая возвращает этот идентификатор.

В-третьих, каждый раз вы создаете новый объект.Это фабричный шаблон, но есть два варианта, как это реализовать.Один из них дает возможность клонировать каждую реализацию и рассматривать каждый экземпляр как прототип.Другой - создать связанную иерархию фабрик, которые строят эти технические объекты.

Если вы идете по пути прототипа, также определите virtual std::shared_ptr<BasicChildTechnology> clone() const =0; в технических классах.В противном случае создайте связанное дерево классов TechnologyFactory или шаблон Factory<T>.Фабрике понадобится что-то вроде label_t label() и std::shared_ptr<BasicChildTechnology> build().

Я собираюсь выбрать здесь прототип.

Построить поиск как:

std::map<label_t, std::shared_ptr<BasicChildTechnology>> lookup;
lookup.add(tech1->label(), tech1);
lookup.add(tech2->label(), tech2);
lookup.add(tech3->label(), tech3);

Тогда:

std::shared_ptr<BasicChildTechnology> getTechnologyObject(const label_t& label)
{
    return lookup[label]->clone();
}

И шаблон фабрики здесь.

Создайте поиск следующим образом:

std::map<label_t, Factory<std::shared_ptr<BasicChildTechnology>>> lookup;
lookup.add(factory1->label(), factory1);
lookup.add(factory2->label(), factory2);
lookup.add(factory3->label(), factory3);

Тогда:

std::shared_ptr<BasicChildTechnology> getTechnologyObject(const label_t& label)
{
    return lookup[label]->build();
}

в обоих случаях поиск выполняется в журнале (N).

0 голосов
/ 29 ноября 2018

То, что вы пытаетесь сделать, имеет разные решения, основанные на вашей точной реализации и том, что на самом деле делают дочерние типы.

Если метод isValid() никогда не опирается на нестатические переменные-члены, isValid() можно сделать статическим.Ваша функция getTechnologyObject() может быть записана в виде:

Technology* getTechnologyObject(const std::string& _string)
{
  if(ConcreteChildTechnology1::isValid(_string)){
    return new ConcreteChildTechnology1(/* arguments go here */);
  } 
  /* follow with the rest */
}

Согласно комментарию пользователя 4581301 вы можете вернуть указатель, чтобы предотвратить нарезку объектов.

Кажется, что ваша иерархия типов имеет размер,Чтобы уменьшить сложность и, возможно, упростить создание объектов, вы можете исследовать некоторую форму композиция вместо наследования.Таким образом, фабричный образец будет иметь больше смысла.Возможно, вы могли бы создать объект Technology на основе того, что он должен делать, используя шаблон декоратора .

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