最近我一直在使用一些模式,但我不知道它是否真的很好。
如下: 我有一组功能,我们称之为 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 * 函数并不明显。此外 - 没有能力dynamic_cast这样的类来确定它是什么。
我非常怀疑这些不仅是这种方法的缺点所以我想对此发表评论。
答案 0 :(得分:1)
听起来你想要Chain of Responsibility模式
abstract class Action {
Action child;
Action(Action child) { this.child = child; }
Action() { }
void doAction(StateContext context);
void execute(StateContext context) {
if (child) child.execute(context);
doAction(context);
}
}
class ZapAction extends Action {
ZapAction(String theString, int theValue, Action child) { ... }
void doAction(Context context) { context.setZap(theString); }
}
Action actionSequenceAlpha = new ZapAction("", 1, new FooAction());
Action actionSequenceBeta = new FooAction(new BarAction(new ZapAction));
优点 - 当您添加新的Action时,不需要使用固定的strategies更改此基础对象,您可以以各种有趣和令人兴奋的方式映射操作,每个对象都有一个单一的责任这是一个很好的标准模式,所以每个人都知道发生了什么。
另一种选择是将序列与Action分开。有一个Action接口,其中包含三个继承它的Actions。然后有一个Sequence
类,其中包含execute方法和List Action
s
class Action { }
class FooAction extends Action { }
class Sequence {
List<Action> actions;
void execute() {
foreach (action : actions) action.execute();
}
}