更多 类
templated Attorney-Client Idiom for more many classes
我试图将律师-客户惯用语(称为密码惯用语)和这两个 classes 一起使用。
我解释一下:
我有一个名为 Secret
的 class,其中包含 name
和 age
作为私有成员。我创建了一个 class Attorney
为 class Secret
.
中的每个成员定义了 2 getters
我想创建 2 个 classes:
showAge
只能访问 1 getter
showAgeAndName
可以访问两个 getters.
到目前为止一切正常,但查看代码,它不是很好维护:如果我向我的 Secret
添加新成员并想要对新的 getter 进行特定访问,我必须添加另一个 class 并以大量复制粘贴结束。
那么是否有更好的选择,例如:使用工厂设计模式/增强模板化 class ...
下面是我的代码:
#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);
}
谢谢
在我看来,这种模式带来的麻烦多于它的价值。
相反,您可能会考虑为每个访问角色定义接口,然后通过对适当接口类型的引用来传递对象。这可能更具可读性和直观性,尽管它仍然需要您为每个角色定义和维护接口。
应根据访问角色选择接口和它们公开的成员函数。您不一定需要为每个功能提供单独的界面。如果您认为您这样做,我会将其视为 code smell 并将其作为重新评估设计的提示。使用代理人-客户/密码模式时也是如此。
Attorney-Client / PassKey 模式的唯一优点是它不需要成员函数是 virtual
。但是很有可能虚函数的性能开销is not important to your application.
缺点是 Attorney-Client / PassKey 模式鼓励您根据特定用户设计 "interfaces"(如访问 Secret
的特定 类)。这将创建 coupling。最好从通用角色的角度考虑,可以适当分配。
我试图将律师-客户惯用语(称为密码惯用语)和这两个 classes 一起使用。
我解释一下:
我有一个名为 Secret
的 class,其中包含 name
和 age
作为私有成员。我创建了一个 class Attorney
为 class Secret
.
我想创建 2 个 classes:
showAge
只能访问 1 gettershowAgeAndName
可以访问两个 getters.
到目前为止一切正常,但查看代码,它不是很好维护:如果我向我的 Secret
添加新成员并想要对新的 getter 进行特定访问,我必须添加另一个 class 并以大量复制粘贴结束。
那么是否有更好的选择,例如:使用工厂设计模式/增强模板化 class ...
下面是我的代码:
#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);
}
谢谢
在我看来,这种模式带来的麻烦多于它的价值。
相反,您可能会考虑为每个访问角色定义接口,然后通过对适当接口类型的引用来传递对象。这可能更具可读性和直观性,尽管它仍然需要您为每个角色定义和维护接口。
应根据访问角色选择接口和它们公开的成员函数。您不一定需要为每个功能提供单独的界面。如果您认为您这样做,我会将其视为 code smell 并将其作为重新评估设计的提示。使用代理人-客户/密码模式时也是如此。
Attorney-Client / PassKey 模式的唯一优点是它不需要成员函数是 virtual
。但是很有可能虚函数的性能开销is not important to your application.
缺点是 Attorney-Client / PassKey 模式鼓励您根据特定用户设计 "interfaces"(如访问 Secret
的特定 类)。这将创建 coupling。最好从通用角色的角度考虑,可以适当分配。