шаблонный идиом «адвокат-клиент» для многих других классов - PullRequest
0 голосов
/ 06 ноября 2018

Я пытался применить идиому Attorney-Client (известный как PassKey Idiom) и это для двух классов.

Я объясняю:

У меня есть класс с именем Secret, который содержит name и age в качестве закрытых членов. Я создал класс Attorney, который определяет 2 получателя для каждого члена класса Secret.

Я хочу создать 2 класса:

  1. showAge, которые имеют доступ только к 1 получателю
  2. showAgeAndName, который имеет доступ к обоим геттерам.

Пока что все работает нормально, но, глядя на код, он плохо обслуживается: если я добавляю новых членов в свой Secret и хочу получить определенный доступ к новым получателям, мне нужно добавить еще один класс и закончить большим количеством копий. -вставить.

Итак, есть ли лучшая альтернатива, например: использование шаблона проектирования Factory / улучшение шаблонного класса ...

Ниже мой код:

#include <string>
#include <iostream>

using namespace std;

class Secret;
class showAge;
class showAgeAndName;

template<typename T>
class Attorney
{
private:
    friend T;
    Attorney(const Attorney&) {}
    Attorney() {}   
};

class Secret
{
public:
    std::string getAge(Attorney<showAge>) noexcept { return "Age is " + to_string((long long)age); }
    std::string getName(Attorney<showAgeAndName>) noexcept { return "Name is " + name; }
private:
    int age{36};
    std::string name{"Mike"};
};

class showAge
{
public:
    showAge() noexcept {};

    void showInfos(Secret& src)
    {
        std::cout << src.getAge(Attorney<showAge>()) << std::endl;
    }
};

class showAgeAndName
{
public:
    showAgeAndName() noexcept {};

    void showInfos(Secret& src)
    {
        std::cout << src.getName(Attorney<showAgeAndName>()) << std::endl;
    }
};

int main() {
    Secret s;
    showAge prA;    
    showAgeAndName prAn;
    prA.showInfos(s);
    prAn.showInfos(s);
}

Спасибо

1 Ответ

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

По моему мнению, эта модель больше проблем, чем стоит.

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

Интерфейсы и предоставляемые ими функции-члены должны быть выбраны в соответствии с ролями доступа. Вам не обязательно нужен отдельный интерфейс для каждой функции. Если вы так думаете, я бы воспринял это как кодовый запах и воспринял бы это как сигнал для переоценки дизайна. Это справедливо и при использовании шаблона Attorney-Client / PassKey.

Единственное преимущество шаблона Attorney-Client / PassKey состоит в том, что он не требует, чтобы функции-члены были virtual. Но весьма вероятно, что затраты производительности виртуальных функций не важны для вашего приложения .

Недостатком является то, что шаблон Attorney-Client / PassKey побуждает вас создавать «интерфейсы» на основе конкретных пользователей (как в определенных классах, которые получают доступ к Secret). Это создает связь . Лучше думать с точки зрения общих ролей, которые могут быть назначены соответствующим образом.

...