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

📄 pat3c.htm

📁 四人帮《设计模式》一书英文版本
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<SCRIPT>
function setFocus() {	
	if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {
	return;
	} else {
	self.focus();
	}
}
</SCRIPT><HTML>

<HEAD><TITLE>Factory Method</TITLE></HEAD>

<BODY	BGCOLOR	= #FFFFFF
	TEXT = #000000
onLoad="setFocus()";
>

<A NAME="top"></A>
<A NAME="FactoryMethod"></A>
<A NAME="intent"></A>
<H2><A HREF="#alsoknownas"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next: 
Also Known As"></A> Intent</H2> 

<A NAME="auto1000"></A>
<P>Define an interface for creating an object, but let subclasses decide
which class to instantiate. Factory Method lets a class defer
instantiation to subclasses.</P>

<A NAME="alsoknownas"><A>
<H2><A HREF="#motivation"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next: 
Motivation"></A> Also Known As</H2> 

<A NAME="auto1001"></A>
<P>Virtual Constructor</P>

<A NAME="motivation"></A>
<H2><A HREF="#applicability"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 
ALT="next: Applicability"></A> Motivation</H2> 

<A NAME="auto1002"></A>
<P>Frameworks use abstract classes to define and maintain relationships
between objects.  A framework is often responsible for creating these
objects as well.</P>

<A NAME="app"></A>
<P>Consider a framework for applications that can present multiple
documents to the user. Two key abstractions in this framework are the
classes Application and Document. Both classes are abstract, and
clients have to subclass them to realize their application-specific
implementations.  To create a drawing application, for example, we
define the classes DrawingApplication and DrawingDocument. The
Application class is responsible for managing Documents and will
create them as required&#151;when the user selects Open or New from a
menu, for example.</P>

<A NAME="auto1003"></A>
<P>Because the particular Document subclass to instantiate is
application-specific, the Application class can't predict the
subclass of Document to instantiate&#151;the Application class only
knows <EM>when</EM> a new document should be created, not <EM>what
kind</EM> of Document to create.  This creates a dilemma: The
framework must instantiate classes, but it only knows about abstract
classes, which it cannot instantiate.</P>

<A NAME="auto1004"></A>
<P>The Factory Method pattern offers a solution.  It encapsulates the
knowledge of which Document subclass to create and moves this
knowledge out of the framework.</P>

<A NAME="107c"></A>
<P ALIGN=CENTER><IMG SRC="fmeth049.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/fmeth049.gif"></P>

<A NAME="auto1005"></A>
<P>Application subclasses redefine an abstract CreateDocument operation
on Application to return the appropriate Document subclass.  Once an
Application subclass is instantiated, it can then instantiate
application-specific Documents without knowing their class.  We call
CreateDocument a <STRONG>factory method</STRONG> because it's responsible
for "manufacturing" an object.</P>

<A NAME="applicability"></A>
<H2><A HREF="#structure"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next: 
Structure"></A> Applicability</H2> 

<A NAME="auto1006"></A>
<P>Use the Factory Method pattern when</P>

<UL>

<A NAME="auto1007"></A>
<LI>a class can't anticipate the class of objects it must create.</LI>
<A NAME="auto1008"></A>
<P></P>
<A NAME="auto1009"></A>
<LI>a class wants its subclasses to specify the objects it creates.</LI>
<A NAME="auto1010"></A>
<P></P>
<A NAME="auto1011"></A>
<LI>classes delegate responsibility to one of several helper subclasses,
and you want to localize the knowledge of which helper subclass is the
delegate.</LI>

</UL>

<A NAME="structure"></A>
<H2><A HREF="#participants"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 
ALT="next: Participants"></A> Structure</H2> 

<P ALIGN=CENTER><IMG SRC="fmethod.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/fmethod.gif"></P>

<A NAME="participants"></A>
<H2><A HREF="#collaborations"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 
ALT="next: Collaborations"></A> Participants</H2>

<UL>

<A NAME="prod-part-facmeth"></A>
<LI><B>Product</B> (Document)

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

    <UL>

    <A NAME="auto1013"></A>
<LI>defines the interface of objects the factory method creates.</LI>

    </UL>

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

<A NAME="auto1015"></A>
<LI><B>ConcreteProduct</B> (MyDocument)

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

    <UL>

    <A NAME="auto1017"></A>
<LI>implements the Product interface.</LI>

    </UL>

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

<A NAME="auto1019"></A>
<LI><B>Creator</B> (Application)

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

    <UL>

    <A NAME="auto1021"></A>
<LI>declares the factory method, which returns an object of type
    Product.  Creator may also define a default
    implementation of the factory method that returns a default
    ConcreteProduct object.</LI>

    <A NAME="auto1022"></A>
<P><!-- extra space --></P>

    <A NAME="auto1023"></A>
<LI>may call the factory method to create a Product object.</LI>

    </UL>

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

<A NAME="auto1025"></A>
<LI><B>ConcreteCreator</B> (MyApplication)

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

    <UL>

    <A NAME="auto1027"></A>
<LI>overrides the factory method to
    return an instance of a ConcreteProduct.</LI>

    </UL>

</UL>

<A NAME="collaborations"></A>
<H2><A HREF="#consequences"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 
ALT="next: Consequences"></A> Collaborations</H2>

<UL>

<A NAME="auto1028"></A>
<LI>Creator relies on its subclasses to define the factory method so
that it returns an instance of the appropriate ConcreteProduct.</LI>

</UL>

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

<A NAME="auto1029"></A>
<P>Factory methods eliminate the need to bind application-specific
classes into your code.  The code only deals with the Product
interface; therefore it can work with any user-defined
ConcreteProduct classes.</P>

<A NAME="auto1030"></A>
<P>A potential disadvantage of factory methods is that clients might have
to subclass the Creator class just to create a particular
ConcreteProduct object.  Subclassing is fine when the client has to
subclass the Creator class anyway, but otherwise the client now must
deal with another point of evolution.</P>

<A NAME="auto1031"></A>
<P>Here are two additional consequences of the Factory Method pattern:</P>

<OL>

<A NAME="auto1032"></A>
<LI><EM>Provides hooks for subclasses.</EM>
Creating objects inside a class with a factory method is always more
flexible than creating an object directly.  Factory Method gives
subclasses a hook for providing an extended version of an object.

<A NAME="auto1033"></A>
<P>In the Document example, the Document class could define a factory
method called CreateFileDialog that creates a default file dialog
object for opening an existing document.  A Document subclass can
define an application-specific file dialog by overriding this factory
method.  In this case the factory method is not abstract but provides
a reasonable default implementation.</LI>
<A NAME="auto1034"></A>
<P></P>
<A NAME="auto1035"></A>
<LI><EM>Connects parallel class hierarchies.</EM>
In the examples we've considered so far, the factory method is only
called by Creators.  But this doesn't have to be the case;
clients can find factory methods useful, especially in the case of
parallel class hierarchies.

<A NAME="auto1036"></A>
<P>Parallel class hierarchies result when a class delegates some of its
responsibilities to a separate class. Consider graphical figures that
can be manipulated interactively; that is, they can be stretched,
moved, or rotated using the mouse. Implementing such interactions
isn't always easy. It often requires storing and updating information
that records the state of the manipulation at a given time.  This
state is needed only during manipulation; therefore it needn't be kept
in the figure object.  Moreover, different figures behave differently
when the user manipulates them.  For example, stretching a line figure
might have the effect of moving an endpoint, whereas stretching a text
figure may change its line spacing.</P>

<A NAME="manip"></A>
<P>With these constraints, it's better to use a separate Manipulator
object that implements the interaction and keeps track of any
manipulation-specific state that's needed.  Different figures will use
different Manipulator subclasses to handle particular interactions.
The resulting Manipulator class hierarchy parallels (at least
partially) the Figure class hierarchy:</P>

<A NAME="fmethod-eg2"></A>
<P ALIGN=CENTER><IMG SRC="fmeth048.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/fmeth048.gif"></P>

<A NAME="auto1037"></A>
<P>The Figure class provides a CreateManipulator factory method that lets
clients create a Figure's corresponding Manipulator. Figure subclasses
override this method to return an instance of the Manipulator subclass
that's right for them.  Alternatively, the Figure class may implement
CreateManipulator to return a default Manipulator instance, and Figure
subclasses may simply inherit that default.  The Figure classes that
do so need no corresponding Manipulator subclass&#151;hence the
hierarchies are only partially parallel.</P>

<A NAME="auto1038"></A>
<P>Notice how the factory method defines the connection between the two
class hierarchies. It localizes knowledge of which classes belong
together.</P>

</OL>

<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>Consider the following issues when applying the Factory Method pattern:</P>

<OL>

<A NAME="auto1040"></A>
<LI><EM>Two major varieties.</EM>
The two main variations of the Factory Method pattern are (1) the case
when the Creator class is an abstract class and does not provide an
implementation for the factory method it declares, and (2) the case
when the Creator is a concrete class and provides a default
implementation for the factory method.  It's also possible to have an
abstract class that defines a default implementation, but this is less
common.

<A NAME="auto1041"></A>
<P>The first case <EM>requires</EM> subclasses to define an implementation,
because there's no reasonable default.  It gets around the dilemma of
having to instantiate unforeseeable classes. In the second case, the
concrete Creator uses the factory method primarily for flexibility.
It's following a rule that says, "Create objects in a separate
operation so that subclasses can override the way they're created."
This rule ensures that designers of subclasses can change the class of
objects their parent class instantiates if necessary.</LI>

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

<A NAME="fact-param-prod"></A>
<LI><EM>Parameterized factory methods.</EM>
Another variation on the pattern lets the factory method create <EM>multiple</EM> kinds of products.  The factory method takes a parameter
that identifies the kind of object to create. All objects the factory
method creates will share the Product interface.  In the Document
example, Application might support different kinds of Documents.  You
pass CreateDocument an extra parameter to specify the kind of document
to create.

<A NAME="unidraw-use-factmeth"></A>
<P>The Unidraw graphical editing framework [<A HREF="bibfs.htm#unidraw_framework" tppabs="http://ultra/development/DesignPatterns/hires/bibfs.htm#unidraw_framework" TARGET="_mainDisplayFrame">VL90</A>] uses
this approach for reconstructing objects saved on disk.  Unidraw
defines a <CODE>Creator</CODE> class with a factory method
<CODE>Create</CODE> that takes a class identifier as an argument.  The
class identifier specifies the class to instantiate.  When Unidraw
saves an object to disk, it writes out the class identifier first and
then its instance variables.  When it reconstructs the object from
disk, it reads the class identifier first.</P>

<A NAME="auto1043"></A>
<P>Once the class identifier is read, the framework calls
<CODE>Create</CODE>, passing the identifier as the parameter.
<CODE>Create</CODE> looks up the constructor for the corresponding class
and uses it to instantiate the object.  Last, <CODE>Create</CODE> calls
the object's <CODE>Read</CODE> operation, which reads the remaining
information on the disk and initializes the object's instance
variables.</P>

<A NAME="auto1044"></A>
<P>A parameterized factory method has the following general form, where
<CODE>MyProduct</CODE> and <CODE>YourProduct</CODE> are subclasses of
<CODE>Product</CODE>:

<A NAME="auto1045"></A>
<PRE>
    class Creator {
    public:
        virtual Product* Create(ProductId);
    };
    
    Product* Creator::Create (ProductId id) {
        if (id == MINE)  return new MyProduct;
        if (id == YOURS) return new YourProduct;
        // repeat for remaining products...
    
        return 0;
    }
</PRE>

⌨️ 快捷键说明

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