这是众所周知的设计模式吗?它叫啥名字?
Posted
技术标签:
【中文标题】这是众所周知的设计模式吗?它叫啥名字?【英文标题】:Is this a well known design pattern? What is its name?这是众所周知的设计模式吗?它叫什么名字? 【发布时间】:2011-02-07 21:34:35 【问题描述】:我在代码中经常看到这种情况,但是当我谈到它时,我不知道这种“模式”的名称
我有一个有 2 个参数的方法,它调用一个有 3 个参数的重载方法,并故意将第 3 个参数设置为空字符串。
public void DoWork(string name, string phoneNumber)
DoWork(name, phoneNumber, string.Empty)
private void DoWork(string name, string phoneNumber, string emailAddress)
//do the work
我这样做的原因是不重复代码,并允许现有的调用者仍然调用只有 2 个参数的方法。
这是一种模式吗?它有名字吗?
【问题讨论】:
称为伸缩图案。看我的回答。 已发送至dry。 【参考方案1】:它实际上不仅仅是方法重载(其中通常相同的方法名称有不同的参数类型),这种特定的模式——其中重载基本上是相同的方法,较短的调用具有默认值的较长的函数来模拟可选参数 - 称为伸缩/伸缩模式,通常在构造函数中看到,但当然可以推广到任何方法。
为了更权威的引用,这里是Effective Java 2nd Edition的摘录,第 2 条:在面对许多构造函数参数时考虑构建器模式 (excerpt online)
传统上,程序员使用伸缩构造函数模式,在该模式中,您提供一个仅具有必需参数的构造函数,另一个具有单个可选参数,第三个具有两个可选参数,依此类推。 ..
同样,通常在构造函数的上下文中讨论伸缩模式(例如,2-arg 构造函数将有一行 this(arg1, arg2, ARG3_DEFAULT);
来调用 3-arg 构造函数等),但我不明白为什么会这样也不能推广到其他方法。
另一个权威引用,不幸的是没有定义模式:Sun Developer Network: How to Write Doc Comments for the Javadoc Tool:
请注意,方法和构造函数是按“伸缩”顺序排列的,这意味着首先是“无 arg”形式,然后是“1 arg”形式,然后是“2 arg”形式,依此类推。
还有一个随机引用,对模式有更明确的定义:I Am Hate Method Overloading (And So Can You!):
伸缩方法
你可能有一个带有一些参数的函数。最后几个参数可能并不那么重要,大多数用户会因为必须弄清楚要传递给他们的内容而烦恼。因此,您创建了更多具有相同名称和更少参数的方法,它们调用“主”方法。
最后这句话直接表明默认参数的语言支持是一个更好的选择。
【讨论】:
@polygenelubricants:非常感谢您的反馈,谢谢!我的观点是,虽然我 100% 同意你的总体想法,但我对这个具体案例并不十分相信。事实上,我们拥有 40 年的 OOP 和 30 年的设计模式,对于如此常见的情况,你几乎找不到世界上 3 个引用“设计模式”(或至少概括这个想法),不要让你认为没有公认的设计模式,可能是因为没有必要?您认为提供的数据足以说明:这就是“伸缩模式”吗? @Claudio:也许这个名字还没有广泛传播,但它被用在Effective Java中,我认为这是一本广为阅读的书.无论如何,让我们开始使用名称而不是根本不命名它。我们正在使用模式(好的或坏的),所以与其让它无名,不如给它起个名字。你知道吗,有些人已经这样做了。【参考方案2】:它的名字是重载,它不是一种设计模式,而是一种 OOP 特性
http://en.wikipedia.org/wiki/Method_overloading
【讨论】:
好吧,我应该把第二个方法私有化,这是重载方法对调用者隐藏的情况,重载方法由父调用。我会调整我的代码,谢谢,有没有这个功能的名称或重载方法的使用? IMO,重载可以被认为是OOP和其他语言支持的设计模式。 说这是“只是方法重载”就像说例如访问者模式是“只是动态调度”。它完美地描述了 OOP 机制,但没有解决设计模式是什么的整个概念。 @polygenelubricants:感谢您的反馈。对“伸缩图案”的唯一参考是您提供的链接。这只是一个人决定给世界上似乎没有其他人使用的特定情况的名称。用户询问是否存在众所周知的模式,并且该名称的 WELL KNOWN 名称是否超载。 从天而降的冰冻水片的众所周知的名字是雪。一年中有 4 个月发生这种情况的模式的名称是冬天。【参考方案3】:不,这不是四种意义上的设计模式,但它在许多不允许默认参数的语言中很常见。
在像 ruby 这样的语言中,您可以执行以下类似操作
def dowork(name, phoneNumber, emailAddress = '')
# code here
end
【讨论】:
【参考方案4】:这是一个辅助方法的例子。谢天谢地,不在四人帮中并不能阻止它成为一种模式。在 helper 是公共的并且 helper 方法是私有的特定情况下,它是封装的一个示例。在这种情况下,可能封装过多。
【讨论】:
【参考方案5】:我想说这几乎是 c#
编辑:好的,您的更新确实让我感到震惊,我看不出您正在尝试使用调用私有方法的公共方法做什么。就公共 api 而言,您可以将所有私有方法代码移动到公共方法中,并为“默认”值设置一个局部变量。还是这两个方法也从类中的其他地方调用?
【讨论】:
【参考方案6】:我猜你的 DoWork
方法应该被称为 CreateContact
或者你对 CreateContact
的调用应该是 DoWork
...
但是这并不是一个真正的模式。这只是method overloading的常用用法。
【讨论】:
是的,我可以将其称为创建联系人,但不想涉及构造函数,因为在我的真实示例中它们是静态方法,因此我将其称为 DoWork。我知道它被称为方法重载,也许我应该把它放在问题中以明确我知道这些是同一方法的重载版本。这是调用者无法直接调用重载方法的情况,我应该将第二个设为私有,我现在将对其进行编辑。这种重载方法的使用是否有一个名称,它们相互调用并且只有一个是公共的? 据我所知,这仍然只是重载的一种使用,而不是一种公认的模式。【参考方案7】:它被称为函数重载。在函数重载中,函数的名称相同,但参数类型或参数数量不同。它也被称为假多态性。它不是一种模式,它是一个基本的 OOP 概念。
【讨论】:
【参考方案8】:我同意@polygenelubricants,但想指出,除了超载外,还可以使用伸缩模式。一个例子是在 Objective-C 中,方法选择器(签名)必须是唯一的并且不能被重载。
- (id)init
return [self initWithParam:0];
- (id)initWithParam:(int)param
// Do real initialization here!
return self;
【讨论】:
以上是关于这是众所周知的设计模式吗?它叫啥名字?的主要内容,如果未能解决你的问题,请参考以下文章