Основанный на политике дизайн и лучшие практики - C++

В Okio мы объявляем два дополнительных набора источников, nativeMain и nativeTest, и настраиваем встроенные исходные наборы источников в зависимости от них:

apply plugin: 'org.jetbrains.kotlin.multiplatform'

kotlin {
  iosX64()
  iosArm64()
  linuxX64()
  macosX64()
  mingwX64('winX64')
  sourceSets {
    nativeMain {
      dependsOn commonMain
    }
    nativeTest {
      dependsOn commonTest
    }

    configure([iosX64Main, iosArm64Main, linuxX64Main, macosX64Main, winX64Main]) {
      dependsOn nativeMain
    }
    configure([iosX64Test, iosArm64Test, linuxX64Test, macosX64Test, winX64Test]) {
      dependsOn nativeTest
    }
  }
}

26
задан Patryk 27 February 2016 в 13:24
поделиться

3 ответа

Вот как я бы реализовал класс:

template<class PenType>
class Writer
{
public:
  Writer(const PenType& pen = PenType()) : pen(pen) {}

  void StartWriting()
  {
    pen.Write();
  }

private:
  PenType pen;
};

Это позволяет пользователю передать конкретный объект Pen в конструктор, если он либо не имеет конструктора по умолчанию, либо вы не хотите, чтобы он использовался, и, во-вторых, он по-прежнему позволяет вам опускать объект PenType, если вы счастливы позволить ему создать его с помощью конструктора по умолчанию. Стандартная библиотека C ++ делает то же самое для многих классов (подумайте, например, о распределителях для контейнерных классов).

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

В общем, дизайн на основе политик не требует наследования. Добавление его в качестве участника также работает. Если вы все же выбираете наследование, сделайте его частным, чтобы не получить проблему, о которой вы упомянули как №4.

25
ответ дан 28 November 2019 в 07:12
поделиться

Это выглядит как хороший пример реализации интеллектуального указателя на основе политик: ссылка . Андрей Александреску описывает реализацию интеллектуального указателя на основе политик в одной из своих книг. Теперь что касается ваших вопросов. У меня есть некоторый опыт в этом вопросе, но его недостаточно, чтобы принимать мои слова как должное:

Ad 1 & 4. Я полагаю, что дизайн на основе политик больше связан с шаблонами, чем наследованием. Вы пишете класс шаблона, а аргументы шаблона - это классы политики, например:

template<class FooPolicy, class BarPolicy>
class Baz {
    // implementation goes here
};

Затем вы используете методы из классов политики в своем классе:

void Baz::someMethod(int someArg) {
    FooPolicy::methodInit();
    // some stuff
    BarPolicy::methodDone();
}

Я использую статические методы в этом примере, потому что часто политика не требует какого-либо состояния. Если это так, вы включаете состояние политики по составу, а не по наследованию:

template<class FooPolicy, class BarPolicy>
class Baz {
  private:
    FooPolicy::State fooState; // might require 'typename' keyword, I didn't
                               // actually tried this in any compiler
    // rest of the Baz class
};

Ad 2. Вы можете написать специализацию шаблона - для определенной комбинации основного класса и его '

14
ответ дан 28 November 2019 в 07:12
поделиться

1 - Эта реализация выглядит верный? Я имею в виду, действительно ли это выглядит как дизайн на основе политик?

Классы политик получают свою полезность от комбинирования поведений для создания разнообразных комбинаций. Когда у вас есть один такой параметр шаблона, это не совсем класс политики.

2 - Теперь я могу прикрепить любые ручки к писатель. Но что я буду делать, когда получу ручка без конструктора по умолчанию (только параметризованные конструкторы)? Как справлюсь ли я с этой ситуацией?

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

Думаю, компилятор заменит PenType с помощью InkPen. Если да, то почему я не умею для вызова просто Write () из StartWriting () вместо префикса имя базового класса (PenType :: Write ())?

Когда вы наследуете от шаблона класса, вы должны указать this-> member или BaseClass :: member.

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

Сохраните PenType как член, как предложено выше. Всегда предпочитайте композицию наследованию, поскольку она позволяет избежать тесных взаимосвязей наследования.

5
ответ дан 28 November 2019 в 07:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: