📄 pat4e.htm
字号:
<SCRIPT>
function setFocus() {
if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {
return;
} else {
self.focus();
}
}
</SCRIPT><HTML><HEAD> <TITLE>Facade</TITLE></HEAD><BODY BGCOLOR = #FFFFFF TEXT = #000000
onLoad="setFocus()";><A NAME="top"></A><A NAME="Facade"></A><A NAME="intent"></A><H2><A HREF="#motivation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Motivation"></A> Intent</H2> <A NAME="auto1000"></A><P>Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystemeasier to use.</P><A NAME="motivation"></A><H2><A HREF="#applicability"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Applicability"></A> Motivation</H2> <A NAME="auto1001"></A><P>Structuring a system into subsystems helps reduce complexity. Acommon design goal is to minimize the communication and dependenciesbetween subsystems. One way to achieve this goal is to introduce a<STRONG>facade</STRONG> object that provides a single, simplified interfaceto the more general facilities of a subsystem.</P><A NAME="facade-eg"></A><P ALIGN=CENTER><IMG SRC="Pictures/facad057.gif" border=0></P><A NAME="auto1002"></A><P>Consider for example a programming environment that gives applicationsaccess to its compiler subsystem. This subsystem contains classessuch as Scanner, Parser, ProgramNode, BytecodeStream, andProgramNodeBuilder that implement the compiler. Some specializedapplications might need to access these classes directly. But mostclients of a compiler generally don't care about details like parsingand code generation; they merely want to compile some code. For them,the powerful but low-level interfaces in the compiler subsystem onlycomplicate their task.</P><A NAME="auto1003"></A><P>To provide a higher-level interface that can shield clients from theseclasses, the compiler subsystem also includes a Compiler class. Thisclass defines a unified interface to the compiler's functionality.The Compiler class acts as a facade: It offers clients a single,simple interface to the compiler subsystem. It glues together theclasses that implement compiler functionality without hiding themcompletely. The compiler facade makes life easier for mostprogrammers without hiding the lower-level functionality from the fewthat need it.</P><P ALIGN=CENTER><IMG SRC="Pictures/facad058.gif"></P><A NAME="applicability"></A><H2><A HREF="#structure"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Structure"></A> Applicability</H2> <A NAME="auto1004"></A><P>Use the Facade pattern when</P><UL><A NAME="auto1005"></A><LI>you want to provide a simple interface to a complex subsystem.Subsystems often get more complex as they evolve. Most patterns, whenapplied, result in more and smaller classes. This makes the subsystemmore reusable and easier to customize, but it also becomes harder touse for clients that don't need to customize it. A facade can providea simple default view of the subsystem that is good enough for mostclients. Only clients needing more customizability will need to lookbeyond the facade.</LI><A NAME="auto1006"></A><P></P><A NAME="auto1007"></A><LI>there are many dependencies between clients and the implementationclasses of an abstraction. Introduce a facade to decouple thesubsystem from clients and other subsystems, thereby promotingsubsystem independence and portability.</LI><A NAME="auto1008"></A><P></P><A NAME="auto1009"></A><LI>you want to layer your subsystems. Use a facade to define an entrypoint to each subsystem level. If subsystems are dependent, then youcan simplify the dependencies between them by making them communicatewith each other solely through their facades.</LI></UL><A NAME="structure"></A><H2><A HREF="#participants"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Participants"></A> Structure</H2> <A NAME="facade-gif"></A><P ALIGN=CENTER><IMG SRC="Pictures/facade.gif"></P><A NAME="participants"></A><H2><A HREF="#collaborations"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Collaborations"></A> Participants</H2><UL><A NAME="auto1010"></A><LI><B>Facade</B> (Compiler)<A NAME="auto1011"></A><P></P> <UL> <A NAME="auto1012"></A><LI>knows which subsystem classes are responsible for a request.</LI><A NAME="auto1013"></A><P></P> <A NAME="auto1014"></A><LI>delegates client requests to appropriate subsystem objects.</LI> </UL><A NAME="auto1015"></A><P></P><A NAME="auto1016"></A><LI><B>subsystem classes</B> (Scanner, Parser, ProgramNode, etc.)<A NAME="auto1017"></A><P></P> <UL> <A NAME="auto1018"></A><LI>implement subsystem functionality.</LI> <A NAME="auto1019"></A><P><!-- extra space --></P> <A NAME="auto1020"></A><LI>handle work assigned by the Facade object.</LI> <A NAME="auto1021"></A><P><!-- extra space --></P> <A NAME="auto1022"></A><LI>have no knowledge of the facade; that is, they keep no references to it.</LI> </UL></UL><A NAME="collaborations"></A><H2><A HREF="#consequences"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Consequences"></A> Collaborations</H2><UL><A NAME="auto1023"></A><LI>Clients communicate with the subsystem by sending requests to Facade,which forwards them to the appropriate subsystem object(s). Althoughthe subsystem objects perform the actual work, the facade may have todo work of its own to translate its interface to subsysteminterfaces.</LI><A NAME="auto1024"></A><P></P><A NAME="auto1025"></A><LI>Clients that use the facade don't have to access its subsystem objectsdirectly.</LI></UL><A NAME="consequences"></A><H2><A HREF="#implementation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Implementation"></A> Consequences</H2> <A NAME="auto1026"></A><P>The Facade pattern offers the following benefits:</P><OL><A NAME="auto1027"></A><LI>It shields clients from subsystem components, thereby reducing the numberof objects that clients deal with and making the subsystem easier touse.</LI><A NAME="auto1028"></A><P></P><A NAME="auto1029"></A><LI>It promotes weak coupling between the subsystem and its clients.Often the components in a subsystem are strongly coupled. Weakcoupling lets you vary the components of the subsystem withoutaffecting its clients. Facades help layer a system and thedependencies between objects. They can eliminate complex orcircular dependencies. This can be an important consequence whenthe client and the subsystem are implemented independently.<A NAME="auto1030"></A><P>Reducing compilation dependencies is vital in large softwaresystems. You want to save time by minimizing recompilation whensubsystem classes change. Reducing compilation dependencies withfacades can limit the recompilation needed for a small change inan important subsystem. A facade can also simplify portingsystems to other platforms, because it's less likely that buildingone subsystem requires building all others.</P></LI><A NAME="auto1031"></A><P></P><A NAME="auto1032"></A><LI>It doesn't prevent applications from using subsystem classes ifthey need to. Thus you can choose between ease of use and generality.</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="auto1033"></A><P>Consider the following issues when implementing a facade:</P><OL><A NAME="auto1034"></A><LI><EM>Reducing client-subsystem coupling.</EM>The coupling between clients and the subsystem can be reduced evenfurther by making Facade an abstract class with concrete subclassesfor different implementations of a subsystem. Then clients cancommunicate with the subsystem through the interface of the abstractFacade class. This abstract coupling keeps clients from knowing whichimplementation of a subsystem is used.<A NAME="auto1035"></A><P>An alternative to subclassing is to configure a Facade object withdifferent subsystem objects. To customize the facade, simply replaceone or more of its subsystem objects.</LI><A NAME="auto1036"></A><P></P><A NAME="auto1037"></A><LI><EM>Public versus private subsystem classes.</EM>A subsystem is analogous to a class in that both have interfaces, andboth encapsulate something—a class encapsulates state andoperations, while a subsystem encapsulates classes. And just as it'suseful to think of the public and private interface of a class, we canthink of the public and private interface of a subsystem.<A NAME="auto1038"></A><P>The public interface to a subsystem consists of classes that allclients can access; the private interface is just for subsystemextenders. The Facade class is part of the public interface, ofcourse, but it's not the only part. Other subsystem classes areusually public as well. For example, the classes Parser and Scannerin the compiler subsystem are part of the public interface.</P><A NAME="auto1039"></A><P>Making subsystem classes private would be useful, but fewobject-oriented languages support it. Both C++ and Smalltalktraditionally have had a global name space for classes. Recently,however, the C++ standardization committee added name spaces to thelanguage [<A HREF="bibfs.htm#c++_namespaces" TARGET="_mainDisplayFrame">Str94</A>], which will let you expose just thepublic subsystem classes.</P></OL><A NAME="samplecode"><A><H2><A HREF="#knownuses"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Known Uses"></A> Sample Code</H2> <A NAME="auto1040"></A><P>Let's take a closer look at how to put a facade on a compilersubsystem.</P><A NAME="auto1041"></A><P>The compiler subsystem defines a {BytecodeStream} class thatimplements a stream of <CODE>Bytecode</CODE> objects. A<CODE>Bytecode</CODE> object encapsulates a bytecode, which can specify machineinstructions. The subsystem also defines a <CODE>Token</CODE> class forobjects that encapsulate tokens in the programming language.</P><A NAME="auto1042"></A><P>The <CODE>Scanner</CODE> class takes a stream of characters and producesa stream of tokens, one token at a time.</P><A NAME="auto1043"></A><PRE> class Scanner { public: Scanner(istream&); virtual ~Scanner(); virtual Token& Scan(); private:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -