⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pat5j.htm

📁 四人帮《设计模式》一书英文版本
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<A NAME="auto1023"></A>
<P></P>

<A NAME="auto1024"></A>
<LI>concrete AbstractClass operations (i.e., operations that are
generally useful to subclasses);</LI>

<A NAME="auto1025"></A>
<P></P>

<A NAME="oper-primitive2"></A>
<LI>primitive operations (i.e., abstract operations);</LI>

<A NAME="auto1026"></A>
<P></P>

<A NAME="auto1027"></A>
<LI>factory methods (see <A HREF="pat3cfs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat3cfs.htm" TARGET="_mainDisplayFrame">Factory Method (107)</A>);
and</LI>

<A NAME="auto1028"></A>
<P></P>

<A NAME="auto1029"></A>
<LI><STRONG>hook operations</STRONG>, which provide default behavior that
subclasses can extend if necessary. A hook operation often does
nothing by default.</LI>

</UL>

<A NAME="auto1030"></A>
<P>It's important for template methods to specify which operations are
hooks (<EM>may</EM> be overridden) and which are abstract operations
(<EM>must</EM> be overridden). To reuse an abstract class effectively,
subclass writers must understand which operations are designed for
overriding.</P>

<A NAME="auto1031"></A>
<P>A subclass can <EM>extend</EM> a parent class operation's behavior by
overriding the operation and calling the parent operation explicitly:

<A NAME="auto1032"></A>
<PRE>
    void DerivedClass::Operation () {
        ParentClass::Operation();
        // DerivedClass extended behavior
    }
</PRE>

<A NAME="auto1033"></A>
<P>Unfortunately, it's easy to forget to call the inherited operation.
We can transform such an operation into a template method to give
the parent control over how subclasses extend it. The idea is to
call a hook operation from a template method in the parent class.
Then subclasses can then override this hook operation:</P>

<A NAME="auto1034"></A>
<PRE>
    void ParentClass::Operation () {
        // ParentClass behavior
        HookOperation();
    }
</PRE>

<A NAME="auto1035"></A>
<P><CODE>HookOperation</CODE> does nothing in <CODE>ParentClass</CODE>:</P>

<A NAME="auto1036"></A>
<PRE>
    void ParentClass::HookOperation () { }
</PRE>

<A NAME="auto1037"></A>
<P>Subclasses override <CODE>HookOperation</CODE> to extend its
behavior:</P>

<A NAME="auto1038"></A>
<PRE>
    void DerivedClass::HookOperation () {
         // derived class extension
    }
</PRE>

<A NAME="implementation"></A>
<H2><A HREF="#samplecode"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next: 
Sample Code"></A> Implementation</H2> 

<A NAME="auto1039"></A>
<P>Three implementation issues are worth noting:</P>

<OL>

<A NAME="auto1040"></A>
<LI><EM>Using C++ access control.</EM>
In C++, the primitive operations that a template method calls can be
declared protected members. This ensures that they are only called by
the template method. Primitive operations that <EM>must</EM> be overridden are
declared pure virtual. The template method itself should not be
overridden; therefore you can make the template method a nonvirtual
member function.</LI>

<A NAME="auto1041"></A>
<P></P>

<A NAME="auto1042"></A>
<LI><EM>Minimizing primitive operations.</EM>
An important goal in designing template methods is to minimize the
number of primitive operations that a subclass must override to flesh
out the algorithm. The more operations that need overriding, the more
tedious things get for clients.</LI>

<A NAME="auto1043"></A>
<P></P>

<A NAME="templ-naming"></A>
<LI><EM>Naming conventions.</EM>
You can identify the operations that should be overridden by adding a
prefix to their names. For example, the MacApp framework for Macintosh
applications [<A HREF="bibfs.htm#macapp" tppabs="http://ultra/development/DesignPatterns/hires/bibfs.htm#macapp" TARGET="_mainDisplayFrame">App89</A>] prefixes template method names with "Do-":
"DoCreateDocument", "DoRead", and so forth.</LI>

</OL>

<A NAME="samplecode"><A>
<H2><A HREF="#knownuses"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next: 
Known Uses"></A> Sample Code</H2> 

<A NAME="auto1044"></A>
<P>The following C++ example shows how a parent class can enforce an
invariant for its subclasses. The example comes from NeXT's
AppKit [<A HREF="bibfs.htm#NeXT_AppKit" tppabs="http://ultra/development/DesignPatterns/hires/bibfs.htm#NeXT_AppKit" TARGET="_mainDisplayFrame">Add94</A>]. Consider a class <CODE>View</CODE> that supports
drawing on the screen. <CODE>View</CODE> enforces the invariant that its
subclasses can draw into a view only after it becomes the "focus,"
which requires certain drawing state (for example, colors and fonts) to
be set up properly.</P>

<A NAME="auto1045"></A>
<P>We can use a <CODE>Display</CODE> template method to set up this state.
<CODE>View</CODE> defines two concrete operations,
<CODE>SetFocus</CODE> and <CODE>ResetFocus</CODE>, that set up and clean up
the drawing state, respectively.  <CODE>View</CODE>'s <CODE>DoDisplay</CODE>
hook operation performs the actual drawing.  <CODE>Display</CODE> calls
<CODE>SetFocus</CODE> before <CODE>DoDisplay</CODE> to set up the drawing
state; <CODE>Display</CODE> calls <CODE>ResetFocus</CODE> afterwards to
release the drawing state.</P>

<A NAME="auto1046"></A>
<PRE>
    void View::Display () {
        SetFocus();
        DoDisplay();
        ResetFocus();
    }
</PRE>

<A NAME="auto1047"></A>
<P>To maintain the invariant, the <CODE>View</CODE>'s clients always call
<CODE>Display</CODE>, and <CODE>View</CODE> subclasses always override
<CODE>DoDisplay</CODE>.</P>

<A NAME="auto1048"></A>
<P><CODE>DoDisplay</CODE> does nothing in <CODE>View</CODE>:</P>

<A NAME="auto1049"></A>
<PRE>
    void View::DoDisplay () { }
</PRE>

<A NAME="auto1050"></A>
<P>Subclasses override it to add their specific drawing behavior:</P>

<A NAME="auto1051"></A>
<PRE>
    void MyView::DoDisplay () {
        // render the view's contents
    }
</PRE>

<A NAME="knownuses"><A>
<H2><A HREF="#relatedpatterns"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 
ALT="next: Related Patterns"></A> Known Uses</H2> 

<A NAME="auto1052"></A>
<P>Template methods are so fundamental that they can be found in almost
every abstract class.  Wirfs-Brock et al. [<A HREF="bibfs.htm#doosw_www" tppabs="http://ultra/development/DesignPatterns/hires/bibfs.htm#doosw_www" TARGET="_mainDisplayFrame">WBWW90,</A>
<A HREF="bibfs.htm#wirfs-brock_cacm" tppabs="http://ultra/development/DesignPatterns/hires/bibfs.htm#wirfs-brock_cacm" TARGET="_mainDisplayFrame"> WBJ90</A>] provide a good overview and
discussion of template methods.</P>

<A NAME="relatedpatterns"></A>
<H2><A HREF="#last"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next: 
navigation"></A> Related Patterns</H2> 

<A NAME="auto1053"></A>
<P><A HREF="pat3cfs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat3cfs.htm" TARGET="_mainDisplayFrame">Factory Methods (107)</A>
are often called by template methods. In the Motivation example,
the factory method DoCreateDocument is called by the template method
OpenDocument.</P>

<A NAME="auto1054"></A>
<P><A HREF="pat5ifs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat5ifs.htm" TARGET="_mainDisplayFrame">Strategy (315)</A>:
Template methods use inheritance to vary part of an algorithm.
Strategies use delegation to vary the entire algorithm.</P>

<A NAME="last"></A>
<P><A HREF="#intent"><IMG SRC="up3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/up3.gif" BORDER=0></A><BR>
<A HREF="pat5kfs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat5kfs.htm" TARGET="_mainDisplayFrame"><IMG SRC="rightar3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/rightar3.gif"
        ALIGN=TOP BORDER=0></A> <A HREF="pat5kfs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat5kfs.htm"
        TARGET="_mainDisplayFrame">Visitor</A><BR>
<A HREF="pat5ifs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat5ifs.htm" TARGET="_mainDisplayFrame"><IMG SRC="leftarr3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/leftarr3.gif"
        ALIGN=TOP BORDER=0></A> <A HREF="pat5ifs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat5ifs.htm"
        TARGET="_mainDisplayFrame">Strategy</A>
</P>

</BODY>

</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -