最近我一直在使用一些模式,但我不知道它是否真的很好。
内容如下:我有一组函数,我们称它们为ActionFoo、ActionBar和ActionZapper。这些在实现上可能不同,但通常用于这些相同的事情。它们可以按顺序一起使用,也可以不一起使用(即其中一些可以单独使用),但在某些情况下,它们确实是组合在一起的。
如果我确实想按顺序使用它们,我通常有两个选择:
1)每次手动编写它们
2)创建类层次结构:
方法#1:
void SomeActionSequence1()
{
ActionFoo1(1);
ActionBar1("Moo");
ActionZapper1("Moo", 42);
}
void SomeActionSequence2()
{
ActionFoo4(1);
ActionBar2("Moo");
ActionZapper1("Moo", 42);
}
这有缺点:
1)我将无法存储状态,并且必须将大量参数传递给这些操作
2)我不会真的有一个连贯的界面,也不能轻松地使用自动补全
方法#2
class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void ActionFoo(int) = 0;
virtual void ActionBar(string) = 0;
virtual void ActionZapper(string, int) = 0;
void ExecuteActionSequence();
};
void Base::ExecuteActionSequence()
{
ActionFoo(1);
ActionBar("Moo");
ActionZapper("Moo", 42);
}
Derived1 : public Base
{
void ActionFoo(int){/*some inplementation*/};
void ActionBar(string){/*some inplementation*/};
void ActionZapper(string, int){/*some inplementation*/};
}
Derived2 : public Base
{
void ActionFoo(int){/*some inplementation*/};
void ActionBar(string){/*some inplementation*/};
void ActionZapper(string, int){/*some inplementation*/};
}
并像这样使用它:
Base* actionSequence = new Derived1();
actionSequence->ExecuteActionSequence();
将使用正确的虚拟机,除了两件小事外,一切似乎都很好:
1) 可扩展性——我必须为每个复杂的动作编写一个类
2) 更重要的是——要么在这些类之间重复很多函数,要么我手上的层次树太复杂了
我有点用“接口对象”模式“规避”这两种方法的问题(注意,这个名字是我的,也许它有一个合适的名字)
我要做的是:
class InterfaceClass
{
public:
InterfaceClass(){};
~InterfaceClass(){};
void ActionFoo(int i)
{
if(fooPlaceholder != 0)
fooPlaceholder(i);
}
void ActionBar(string str)
{
if(barPlaceholder != 0)
barPlaceholder(str);
}
void ActionZapper(string str, int i)
{
if(zapperPlaceholder != 0)
zapperPlaceholder(str, i);
};
void ExecuteActionSequence();
std::function<void(int)> fooPlaceholder;
std::function<void(string)> barPlaceholder;
std::function<void(string, int)> zapperPlaceholder;
};
void InterfaceClass::ExecuteActionSequence()
{
ActionFoo(1);
ActionBar("Moo");
ActionZapper("Moo", 42);
}
在我的应用程序中,我这样做:
InterfaceClass complexAction;
complexAction.fooPlaceholder = ActionFoo;
complexAction.barPlaceholder = ActionBar;
complexAction.zapperPlaceholder = ActionZapper;
complexAction.ExecuteActionSequence();
请注意,ActionFoo、ActionBar和ActionZapper是免费功能,但同时我在界面中使用它们。另外 - 我可以轻松地在这些函数的实现之间切换,即使在运行时(如果我需要这个)。
这种方法的优点是 - 不需要为新操作创建单独的类结构,并且没有Action*函数的代码重复。此外 - 所有函数只能在 complexAction 被初始化的地方被带到范围内。
缺点是,我认为,在InterfaceClass对象中使用哪个Action*函数并不明显。另外 - 没有能力对这样的类进行动态转换来确定它是什么。
我高度怀疑这些不仅是这种方法的缺点,所以我想对此发表评论。