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