我应该如何设计一个允许可选操作的方法?

时间:2010-06-28 00:44:34

标签: language-agnostic design-patterns

例如,假设我:

class Gundam00 extends Gundam implements MobileSuit {
    ...

    public void fight(final List<MobileSuit> mobiruSuitso, final List<Gundam> theOtherDudes, final List<Person> casualities) {
        ....
    }
}

假设其他人和伤亡参数是可选的。如何使此方法尽可能干净?我想过让布尔指出它们是否为空,然后根据需要进行检查。

对于每个参数组合,我也可以使用不同版本的方法,但我认为会有很多代码重复。

有什么建议吗?

4 个答案:

答案 0 :(得分:3)

我发现过去的2-3个参数,能够记住函数的所有参数都会受到影响。并且可以理解。

传递命名参数可以提供帮助。具有类似哈希的文字语法的语言使这非常简单。拿JavaScript:

g = new Gundam00();
g.fight({opponent: enemy, casualties: 'numerous'});

您还可以利用可变长度参数功能来处理此问题(将奇数参数视为名称,甚至将参数视为实际参数)。

g.fight('opponent',enemy,'casualties', 'numerous');

有些语言实际上直接支持命名参数(参见:http://en.wikipedia.org/wiki/Named_parameter#Use_in_programming_languages)。

最后,您可能需要考虑使用一些调用Fluent接口(http://en.wikipedia.org/wiki/Fluent_interface)来添加其他方法。基本上,你有方法调用返回对象本身,所以你可以一起链接调用:

g.opponent(enemy).casualties('numerous').fight();

如果您使用明显/静态类型的以类为重点的语言,这可能是最简单的选择。

更新

回应Setsuna的评论......在最后一个例子中,如果你有奢侈的话,你可以制作像opponentcasualties这样的方法,这些方法不会影响任何内部状态或以任何其他方式计算,而不是设置它们被命名的参数。他们只是设置内部属性,然后所有实际工作都在fight等动作方法中进行。

如果你不能这样做(或者如果你不喜欢编写操作是亚原子的方法),那么你可以在这个想法与类似哈希的文字理念之间找到一个中间点,并创建你自己的集合类专门用于调用命名参数:

n = new NArgs();  
g.fight(n.arg('opponent',enemy).arg('casualties','numerous').arg('motion','slow'));

稍微笨拙一点,但是它将命名参数问题分开并允许你保持你的方法更加原子化,并且NArgs可能很容易实现,只需围绕一种类型的Collection(HashTable?)包装一些方法或其他以您的语言提供的。

答案 1 :(得分:2)

添加方法。重载方法通常是反模式和其他人的重构机会。

http://www.codinghorror.com/blog/2007/03/curlys-law-do-one-thing.html

答案 2 :(得分:0)

  

我想过让布尔表示他们是否为空,然后检查它们并做出相应的反应。

或者......你可以检查它们是否为空。

if(theOtherDudes == null)
    ...

答案 3 :(得分:0)

如果您的类中只有一个“main方法”,那么您可以将可选参数实现为getter / setter函数。例如:

public void setOtherDudes(final List<Gundam> theOtherDudes) {} // for input arguments
public List<Person> getCasualities() {} // for output arguments

然后,在您的文档中,请注意,如果调用者有任何可选的输入参数,则必须在调用fight()之前传入它,并且fight()时可选输出值可用调用。

如果有许多可选参数,这是值得的。否则,我建议将方法重载为最简单的方法。