我经常发现自己正在创建使用此表单的类(A):
abstract class Animal {
public void Walk() {
// TODO: do something before walking
// custom logic implemented by each subclass
WalkInternal();
// TODO: do something after walking
}
protected abstract void WalkInternal();
}
class Dog : Animal {
protected override void WalkInternal() {
// TODO: walk with 4 legs
}
}
class Bird : Animal {
protected override void WalkInternal() {
// TODO: walk with 2 legs
}
}
而不是这种形式(B):
abstract class Animal {
public abstract void Walk();
}
class Dog : Animal {
public override void Walk() {
// TODO: do something before walking
// custom logic implemented by each subclass
// TODO: walk with 4 legs
// TODO: do something after walking
}
}
class Bird : Animal {
public override void Walk() {
// TODO: do something before walking
// custom logic implemented by each subclass
// TODO: walk with 2 legs
// TODO: do something after walking
}
}
正如您所看到的,表单A的优点在于,每次实现子类时,都不需要记住包含初始化和终结逻辑。这比B形式更不容易出错。
命名这些方法的标准惯例是什么?
我喜欢命名公共方法Walk
,因为那时我可以调用Dog.Walk()
,它看起来比Dog.WalkExternal()
更好。但是,我不喜欢我为受保护方法添加后缀“Internal”的解决方案。我正在寻找一个更标准化的名字。
顺便问一下,这个设计模式有名字吗?
答案 0 :(得分:11)
我不确定是否有标准的命名约定。除WalkInternal
外,其他替代方案可能是DoWalk
或WalkImpl
。
答案 1 :(得分:10)
顺便问一下,这个设计模式有名字吗?
您的第一个示例使用了模板方法模式的各个方面,类似于Herb Sutter所谓的“非虚拟接口习语”:
答案 2 :(得分:8)
我更喜欢使用后缀Core
来命名我的虚拟或抽象方法,以表明该方法应包含执行某些操作的核心逻辑。
所有参数检查并引发我在方法中执行的可能事件,这些事件调用Core-Methods。
abstract class Animal {
public void Walk() {
// TODO: do something before walking
// possible Argument checks and event raising
// custom logic implemented by each subclass
WalkCore();
// TODO: do something after walking
}
protected abstract void WalkCore();
}
class Dog : Animal {
protected override void WalkCore() {
// TODO: walk with 4 legs
}
}
class Bird : Animal {
protected override void WalkCore() {
// TODO: walk with 2 legs
}
}
我认为没有正式的命名准则,这取决于你。但它应该与您定义的所有类和虚拟/抽象方法保持一致。
如果您遵循模板方法并希望提供可扩展性点,则"Framework Design Guidelines"建议使用 Core 后缀。
答案 3 :(得分:3)
好问题。该模式是有效的,我使用它很多。我也同意WalkInternal
不是一个理想的名字。
在这个例子中,我相信你没有正确地解决问题。
不要重命名“内部”方法,而是查看“外部”公共方法。它被称为Walk
,但它有代码段(//do something before walking
和//do something after walking
),它清楚地表明它不仅包含“行走”的逻辑。也许这种方法应该被称为Exercise
或GoToTheShops
- 或者您可以想到的任何描述您正在做的事情的创意名称。无论方法是什么,它绝对是步行+其他一些前/后步行动作的超集。
我最近开发的类似示例有一个名为Complete
的公共方法和一个名为Save
的虚拟方法,因此:
总之,抽象方法应该被称为Walk
,而应该将您的公共方法重命名为更准确地描述“做某事/走路/做某事”过程的事情。
编辑:如果Walk
类没有向WalkInternal
类添加任何重要值或逻辑,那么我会质疑它是否是必需的。如果它确实添加了逻辑,则应重命名它以反映其新功能。
答案 4 :(得分:2)
我使用下划线大写情况的约定来进行抽象覆盖,所以Dog._Walk,虽然我偶尔会怀疑是否有更好的方法。
我比WalkInternal更喜欢DoWalk - 它更短,更舒适;传达了一种快速和前瞻性的想法。 “做”任何事情都会让我误以为止,就像“我的”对象那样。我喜欢我的下划线,其次是大写字母会议,但仍然是。
现实生活中的好问题
干杯,
Berryl
答案 5 :(得分:0)
对于提供模板方法主要行为的方法,我使用WalkOverride
之类的名称。基类将它实现为protected abstract
方法(派生类必需提供实现)或protected virtual
空/非空方法(派生类可以可选提供/覆盖实现)。可以在Microsoft的各种XAML框架中找到示例,其中包含MeasureOverride
和ArrangeOverride
等方法。 (WalkCore
模式@Jehof提及用于命名模板方法本身。)
对于派生类可以为其自身目的而选择响应的“事件”(与定义模板方法的行为相反),我使用OnWalking
和{{1}之类的名称}}。这些中的每一个通常在基类中实现为具有空方法体的OnWalked
方法。
答案 6 :(得分:0)
此模式的名称为“ Template Method Pattern”
在C#中,要被派生类覆盖的方法以“ On”开头。这种命名背后的逻辑是,派生类是对概念上内部事件的响应的自定义。这导致与C#的其他(现在已弃用的)使用“ On”引发事件产生了一些混淆,但这是C#特有的旧问题,并且不再存在。
class BaseClass
{
protected virtual void OnInitialize() {};
private PreInitialize() {}
private PostInitialize() {}
void Initialize()
{
PreInitialize();
OnInitialize();
PostInitialize();
}
}
class DerivedClass : BaseClass
{
protected override void OnInitialize() { /*do whatever*/ }
}
答案 7 :(得分:-2)
方法是采取行动的手段,按照规则进行操作,方法名称应该是动词或动词短语。它适用于方法,无论它们在何处声明。对我来说Dog.Walk看起来比Dog.WalkInternal.And更自然。是的命名方法更多的是指导而不是设计模式:)。如果你是.Net的人,那么我将推荐Brad Adam和Krzystof Cwalina的“Framework Design GuideLines”一书,它清楚地解决了这些问题。