题
在我参加的几个最近的项目中,我几乎沉迷于以下编码模式: (我不确定是否有专有名称,但是无论如何...)
假设某个对象处于某种确定的状态,我们不会从外部改变这种状态。这些变化可能意味着任何行为,可以调用任何算法,但事实是,它们专注于改变状态 (成员国,数据状态等...) 某些对象。
让我们称呼一种更改这些对象的离散方式 Mutator
. Mutators
被应用一次 (一般来说) 他们有一些内部方法 apply(Target& target, ...)
, ,这立即挑衅改变对象的状态 (实际上,它们是某种功能对象)。
它们也很容易被吸收到 链 并应用一对一(Mutator m1, m2, ...
);他们还可以衍生出一些基本 BasicMutator
和 virtual void apply(...)
方法。
我介绍了名为 InnerMutator
和 ExplicitMutator
在访问方面有所不同 - 首先也可以改变 内部状态 对象的,应被称为朋友(friend InnerMutator::access;
).
在这些项目中,我的逻辑转向以下方式工作:
- 准备可用的突变器,选择要应用的
- 创建并设置
object
到某个确定的状态 foreach (mutator) mutator.apply(object);
现在的问题。
该方案转为运行良好,并且 (对我来说) 似乎是一些非标准但有用的设计模式的样本。
让我感到不舒服的是
InnerMutator
东西。 我认为将突变器宣布为每个对象可以更改的对象是一个好主意,我不会找到适当的选择。这种情况可以通过
Mutators
还是您可以建议一些替代模式以相同的结果?
谢谢。
解决方案
我希望这不是进攻性的,但是我不禁认为这种设计是一个过于简单的问题,解决了一个相当简单的问题。
例如,为什么需要聚集突变器?一个人只能写:
template <class T>
void mutate(T& t)
{
t.mutate1(...);
t.mutate2(...);
t.mutate3(...);
}
有您的聚合突变器,仅是一个简单的函数模板,依靠静态多态性,而不是组合的突变器列表制造一个超级突击器。
我曾经做过可能相当相似的事情。我制作了可以由操作员&&合并为应用两个操作数的超级函数对象(按从左到右的顺序)组合的函数对象,以便可以像以下方式一样编写代码:
foreach(v.begin(), v.end(), attack && burn && drain);
它真的很整洁,当时对我来说似乎真的很聪明,而且非常有效,因为它可以生成新的功能对象(不涉及运行时机制),但是当我的同事看到它时,他们以为我很疯狂。回想起来,我试图将所有内容都塞入功能风格的编程中,该编程具有有用性,但可能不应该在C ++中过度挂起。写作本来很容易:
BOOST_FOR_EACH(Something& something, v)
{
attack(something);
burn(something);
drain(something);
}
当然,它是更多的代码行,但它具有集中式和易于调试的好处,并且不会向使用我的代码工作的其他人介绍外星概念。我发现重点放在紧密的逻辑上而不是试图强制减少代码线的情况下,我发现更有益。
我建议您对此深入思考,并真正考虑是否值得继续进行基于突变器的设计,无论它多么聪明和紧密。如果其他人无法快速理解它,除非您拥有促进作者的权威,否则很难说服人们喜欢它。
至于Innermutator,我认为您应该像瘟疫一样避免它。拥有可以在这里尽可能直接修改类内部的外部突变器类,这完全击败了拥有内部设备的许多目的。
其他提示
简单地做那些 Mutator
他们正在改变的课程的方法?如果您希望有几个类具有共同的功能,那么为什么不使它们从同一基类继承?这样做将解决我想象的所有内部突变器不适。
如果要排队更改,则可以将它们作为函数调用集存储到类中的方法。