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

📄 pat3a.htm

📁 Design Pattern 设计模式
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<SCRIPT>
function setFocus() {	
	if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {
	return;
	} else {
	self.focus();
	}
}
</SCRIPT><HTML><HEAD><TITLE>Abstract Factory</TITLE></HEAD><BODY	BGCOLOR	= #FFFFFF	TEXT = #000000
onLoad="setFocus()";><A NAME="top"></A><A NAME="AbstractFactory"></A><A NAME="intent"></A><H2><A HREF="#alsoknownas"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Also Known As"></A> Intent</H2> <A NAME="auto1000"></A><P>Provide an interface for creating families of related or dependentobjects without specifying their concrete classes.</P><A NAME="alsoknownas"></A><H2><A HREF="#motivation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Motivation"></A>Also Known As</H2> <A NAME="auto1001"></A><P>Kit</P><A NAME="motivation"></A><H2><A HREF="#applicability"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Applicability"></A> Motivation</H2> <A NAME="auto1002"></A><P>Consider a user interface toolkit that supports multiple look-and-feelstandards, such as Motif and Presentation Manager.  Differentlook-and-feels define different appearances and behaviors for userinterface "widgets" like scroll bars, windows, and buttons.  To beportable across look-and-feel standards, an application should nothard-code its widgets for a particular look and feel.  Instantiatinglook-and-feel-specific classes of widgets throughout the applicationmakes it hard to change the look and feel later.</P><A NAME="widgetfactory"></A><P>We can solve this problem by defining an abstract WidgetFactory classthat declares an interface for creating each basic kind of widget.There's also an abstract class for each kind of widget, and concretesubclasses implement widgets for specific look-and-feel standards.WidgetFactory's interface has an operation that returns a new widgetobject for each abstract widget class.  Clients call these operationsto obtain widget instances, but clients aren't aware of the concreteclasses they're using.  Thus clients stay independent of theprevailing look and feel.</P><P ALIGN=CENTER><IMG SRC="Pictures/abfac109.gif"><A NAME="auto1003"></A><P>There is a concrete subclass of WidgetFactory for each look-and-feelstandard.  Each subclass implements the operations to create theappropriate widget for the look and feel.  For example, theCreateScrollBar operation on the MotifWidgetFactory instantiates andreturns a Motif scroll bar, while the corresponding operation on thePMWidgetFactory returns a scroll bar for Presentation Manager.Clients create widgets solely through the WidgetFactory interface andhave no knowledge of the classes that implement widgets for aparticular look and feel.  In other words, clients only have to committo an interface defined by an abstract class, not a particularconcrete class.</P><A NAME="auto1004"></A><P>A WidgetFactory also enforces dependencies between the concrete widgetclasses.  A Motif scroll bar should be used with a Motif button and aMotif text editor, and that constraint is enforced automatically as aconsequence of using a MotifWidgetFactory.</P><A NAME="applicability"></A><H2><A HREF="#structure"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Structure"></A> Applicability</H2> <A NAME="auto1005"></A><P>Use the Abstract Factory pattern when</P><UL><A NAME="auto1006"></A><LI>a system should be independent of how its products are created,composed, and represented.</LI><A NAME="auto1007"></A><P></P><A NAME="auto1008"></A><LI>a system should be configured with one of multiple families of products.<A NAME="auto1009"></A><P></P><A NAME="auto1010"></A><LI>a family of related product objects is designed to be usedtogether, and you need to enforce this constraint.<A NAME="auto1011"></A><P></P><A NAME="auto1012"></A><LI>you want to provide a class library of products, and you wantto reveal just their interfaces, not their implementations.</UL><A NAME="structure"></A><H2><A HREF="#participants"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Participants"></A> Structure</H2> <P ALIGN=CENTER><IMG SRC="Pictures/abfac108.gif"><A NAME="participants"></A><H2><A HREF="#collaborations"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Collaborations"></A> Participants</H2><UL><A NAME="auto1013"></A><LI><B>AbstractFactory</B> (WidgetFactory)</LI><A NAME="auto1014"></A><P></P>    <UL>    <A NAME="auto1015"></A><LI>declares an interface for operations that create abstract product     objects.</LI>    </UL><A NAME="auto1016"></A><P></P><A NAME="auto1017"></A><LI><B>ConcreteFactory</B> (MotifWidgetFactory, PMWidgetFactory)</LI><A NAME="auto1018"></A><P></P>    <UL>    <A NAME="auto1019"></A><LI>implements the operations to create concrete product objects.</LI>    </UL><A NAME="auto1020"></A><P></P><A NAME="auto1021"></A><LI><B>AbstractProduct</B> (Window, ScrollBar)</LI><A NAME="auto1022"></A><P></P>    <UL>    <A NAME="auto1023"></A><LI>declares an interface for a type of product object.</LI>    </UL><A NAME="auto1024"></A><P></P><A NAME="auto1025"></A><LI><B>ConcreteProduct</B> (MotifWindow, MotifScrollBar)</LI><A NAME="auto1026"></A><P></P>    <UL>    <A NAME="auto1027"></A><LI>defines a product object to be created by the corresponding concrete    factory.</LI>    <A NAME="auto1028"></A><P><!-- extra space --></P>    <A NAME="auto1029"></A><LI>implements the AbstractProduct interface.</LI>    </UL><A NAME="auto1030"></A><P></P><A NAME="auto1031"></A><LI><B>Client</B></LI><A NAME="auto1032"></A><P></P>    <UL>    <A NAME="auto1033"></A><LI>uses only interfaces declared by AbstractFactory and    AbstractProduct classes.</LI>    </UL></UL><A NAME="collaborations"></A><H2><A HREF="#consequences"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Consequenses"></A> Collaborations </H2><UL><A NAME="auto1034"></A><LI>Normally a single instance of a ConcreteFactory class is created atrun-time.  This concrete factory creates product objects having aparticular implementation.  To create different product objects,clients should use a different concrete factory.</LI><A NAME="auto1035"></A><P></P><A NAME="auto1036"></A><LI>AbstractFactory defers creation of product objects to its ConcreteFactorysubclass.</LI></UL><A NAME="consequences"></A> <H2><A HREF="#implementation"><IMGSRC="gifsb/down3.gif" BORDER=0 ALT="next: Implementation"></A> Consequences</H2> <A NAME="auto1037"></A><P>The Abstract Factory pattern has the following benefits and liabilities:</P><OL><A NAME="auto1038"></A><LI><EM>It isolates concrete classes.</EM>The Abstract Factory pattern helps you control the classes of objectsthat an application creates.  Because a factory encapsulates theresponsibility and the process of creating product objects, itisolates clients from implementation classes.  Clients manipulateinstances through their abstract interfaces.  Product class names areisolated in the implementation of the concrete factory; they do notappear in client code.</LI><A NAME="auto1039"></A><P></P><A NAME="prodobj-exchange"></A><LI><EM>It makes exchanging product families easy.</EM>The class of a concrete factory appears only once in anapplication&#151;that is, where it's instantiated.  This makes it easy tochange the concrete factory an application uses.  It can usedifferent product configurations simply by changing the concretefactory. Because an abstract factory creates a complete family ofproducts, the whole product family changes at once.  In our userinterface example, we can switch from Motif widgets to PresentationManager widgets simply by switching the corresponding factory objectsand recreating the interface.</LI><A NAME="auto1040"></A><P></P><A NAME="auto1041"></A><LI><EM>It promotes consistency among products.</EM>When product objects in a family are designed to work together, it'simportant that an application use objects from only one family at atime.  AbstractFactory makes this easy to enforce.</LI><A NAME="auto1042"></A><P></P><A NAME="auto1043"></A><LI><EM>Supporting new kinds of products is difficult.</EM>Extending abstract factories to produce new kinds of Products isn'teasy.  That's because the AbstractFactory interface fixes the set ofproducts that can be created. Supporting new kinds of productsrequires extending the factory interface, which involves changing theAbstractFactory class and all of its subclasses.  We discuss one solutionto this problem in the Implementation section.</LI></OL><A NAME="implementation"></A><H2><A HREF="#samplecode"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Sample Code"></A> Implementation</H2> <A NAME="auto1044"></A><P>Here are some useful techniques for implementing the Abstract Factorypattern.</P><OL><A NAME="single-absfact"></A><LI><EM>Factories as singletons.</EM>An application typically needs only one instance of a ConcreteFactoryper product family.  So it's usually best implemented as a<A HREF="pat3efs.htm" TARGET="_mainDisplayFrame">Singleton (127)</A>.<A NAME="auto1045"></A><P></P><A NAME="prodobj-creat-absfact"></A><LI><EM>Creating the products.</EM> AbstractFactory only declaresan <EM>interface</EM> for creating products. It's up to ConcreteProductsubclasses to actually create them.  The most common way to do thisis to define a factory method (see <A HREF="pat3cfs.htm" TARGET="_mainDisplayFrame">Factory Method (107)</A>) for each product.  A concretefactory will specify its products by overriding the factory methodfor each.  While this implementation is simple, it requires a newconcrete factory subclass for each product family, even if theproduct families differ only slightly.<A NAME="proto-imp-absfact"></A><P>If many product families are possible, the concrete factory canbe implemented using the <A HREF="pat3dfs.htm" TARGET="_mainDisplayFrame">Prototype (117)</A>pattern.  The concrete factory is initialized with a prototypicalinstance of each product in the family, and it creates a new productby cloning its prototype. The Prototype-based approach eliminatesthe need for a new concrete factory class for each new productfamily.</P><A NAME="auto1046"></A><P>Here's a way to implement a Prototype-based factory in Smalltalk.  Theconcrete factory stores the prototypes to be cloned in a dictionarycalled <CODE>partCatalog</CODE>. The method <CODE>make:</CODE> retrieves theprototype and clones it:</P><A NAME="auto1047"></A><PRE>    make: partName        ^ (partCatalog at: partName) copy</PRE><A NAME="auto1048"></A><P>The concrete factory has a method for adding parts to the catalog.</P><A NAME="auto1049"></A><PRE>    addPart: partTemplate named: partName        partCatalog at: partName put: partTemplate</PRE><A NAME="auto1050"></A><P>Prototypes are added to the factory by identifying them with a symbol:</P><A NAME="auto1051"></A><PRE>    aFactory addPart: aPrototype named: #ACMEWidget</PRE><A NAME="auto1052"></A><P>A variation on the Prototype-based approach is possible in languagesthat treat classes as first-class objects (Smalltalk and Objective C,for example).  You can think of a class in these languages as adegenerate factory that creates only one kind of product.  You canstore <EM>classes</EM> inside a concrete factory that create the variousconcrete products in variables, much like prototypes.  These classes

⌨️ 快捷键说明

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