问题
I was trying to apply the Attorney-Client Idiom (know as PassKey Idiom) and this for two classes.
I explain :
I have a class named Secret
which contains name
and age
as private members. I have created a class Attorney
which defines 2 getters for each memeber in class Secret
.
I want to create 2 classes:
showAge
which only have access to 1 gettershowAgeAndName
which has access to both getters.
So far all works fine, but looking at the code, it not well maintainable : if I add new members to my Secret
and want a specific access to new getters I have to add another class and end with lot of copy-paste.
So is there a better alternative like : using Factory design pattern / enhance the templated class ...
Below is my code:
#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);
}
Thank you
回答1:
In my opinion this pattern is more trouble than it's worth.
Instead, maybe you'd consider defining interfaces for each access role, then pass the object around by references to the appropriate interface type. This is likely to be far more readable and intuitive, although it still requires you to define and maintain interfaces for each role.
The interfaces and which member functions they expose should be chosen to suit the access roles. You do not necessarily need a separate interface for each function. If you think you do, I'd view that as a code smell and take it as a cue to reevaluate the design. This is true when using the Attorney-Client / PassKey pattern as well.
The only advantage the Attorney-Client / PassKey pattern has is that it doesn't require the member functions to be virtual
. But it is very likely that the performance cost of virtual functions is not important to your application.
A disadvantage is that the Attorney-Client / PassKey pattern encourages you to design the "interfaces" based on specific users (as in specific classes that access the Secret
). This creates coupling. It is better to think in terms of generic roles, which can be assigned as appropriate.
来源:https://stackoverflow.com/questions/53172759/templated-attorney-client-idiom-for-more-many-classes