可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I frequently find myself creating classes which use this form (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
}
}
Rather than this form (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
}
}
As you can see, the nice thing about form A is that every time you implement a subclass, you don't need to remember to include the initialization and finalization logic. This is much less error prone than form B.
What's a standard convention for naming these methods?
I like naming the public method Walk
since then I can call Dog.Walk()
which looks better than something like Dog.WalkExternal()
. However, I don't like my solution of adding the suffix "Internal" for the protected method. I'm looking for a more standardized name.
Btw, is there a name for this design pattern?
回答1:
I'm not sure if there is a standard naming convention for this. Besides WalkInternal
, other alternatives might be DoWalk
or WalkImpl
.
回答2:
Btw, is there a name for this design pattern?
Your first example uses aspects of the Template Method pattern and is similar to what Herb Sutter calls the "Non-virtual Interface Idiom":
- http://www.gotw.ca/publications/mill18.htm
回答3:
I prefer to name my virtual or abstract methods with the suffix Core
, to indicate, that the method should contain the core logic to do something.
All argument checks and raising possible events I do in the method, that calls the 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
}
}
I think there is no offical naming guideline for this, and it´s up to you. But it should be consistent for all classes and virtual/abstract methods you define.
The "Framework Design Guidelines" suggest to use the Core suffix if you follow the Template Method and want to provide extensibility points.
回答4:
Good question. The pattern is valid and I use it a lot. I also agree that WalkInternal
is not an ideal name.
In this example I believe you are not framing the problem correctly.
Rather than renaming the 'internal' method, look at your 'external' public method. It's called Walk
, but it has code snippets (//do something before walking
and //do something after walking
) which clearly shows that it contains more than just the logic for 'Walking'. Maybe this method should be called Exercise
or GoToTheShops
- or whatever creative name you can think of that describes what you are doing. Whatever the method is, it's definitely a superset of Walking + some other pre / post walking actions.
A similar example that I've recently developed had a public method called Complete
, and a virtual called Save
, so that:
- Every class needed to 'Complete'
- Different implementations would have their own 'Save' method
- 'Complete' would also perform some validation, notification, etc
In summary, the abstract method should be called Walk
, and instead you should rename your public method to something that more accurately describes the 'do something / Walk / do something' process.
edit: If the Walk
class doesn't add any significant value or logic to the WalkInternal
class then I would question whether it is required. If it does add logic, then it should be renamed to reflect its new function.
回答5:
I use the convention of an underscore capitalized case for abstract overrides, so Dog._Walk, although I more than occasionally wonder if there wasn't a better way.
I like DoWalk better than WalkInternal - it's shorter & conveys the idea that its an override quickly and upfront. "Do" anything kind of rubs me the wrong way though, kind of like "My" object does. I like my underscore followed by capital letter convention best, still.
Good real life question though
Cheers,
Berryl
回答6:
For a method that provides a template method's primary behavior, I use names like WalkOverride
. The base class implements it as either a protected abstract
method (derived class is required to provide implementation) or a protected virtual
empty/non-empty one (derived class may optionally provide/override implementation). Examples can be found in Microsoft's various XAML frameworks with methods such as MeasureOverride
and ArrangeOverride
. (The WalkCore
pattern @Jehof mentions is used there to name the template method itself.)
For "events" to which the derived class can optionally respond for its own purposes (as opposed to defining the template method's behavior), I use names like OnWalking
and OnWalked
. Each of these is usually implemented in the base class as a protected virtual
method with an empty method body.
回答7:
Methods are means of taking action and going by that rule method names should be either verb or verb phrases.And its applicable to methods irrespective of where they are declared.For me Dog.Walk looks more natural than Dog.WalkInternal.And yes naming of method is more of a guideline than a design pattern :).If you are a .Net guy , then I will recommend "Framework Design GuideLines" book by Brad Adam and Krzystof Cwalina , which clearly address such problems.