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

📄 pat4e.htm

📁 设计模式英文版 作者:Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides 四人帮的书。 学设计模式的必读的书籍!经典中的经典
💻 HTM
📖 第 1 页 / 共 2 页
字号:
</PRE>

<A NAME="auto1044"></A>
<P>The class <CODE>Parser</CODE> uses a <CODE>ProgramNodeBuilder</CODE> to construct a
parse tree from a <CODE>Scanner</CODE>'s tokens.</P>

<A NAME="auto1045"></A>
<PRE>
    class Parser {
    public:
        Parser();
        virtual ~Parser();
    
        virtual void Parse(Scanner&amp;, ProgramNodeBuilder&amp;);
    };
</PRE>


<A NAME="auto1046"></A>
<P><CODE>Parser</CODE> calls back on <CODE>ProgramNodeBuilder</CODE> to build
the parse tree incrementally.  These classes interact according to the
<A HREF="pat3bfs.htm" TARGET="_mainDisplayFrame">Builder&nbsp;(97)</A> pattern.</P>

<A NAME="auto1047"></A>
<PRE>
    class ProgramNodeBuilder {
    public:
        ProgramNodeBuilder();
    
        virtual ProgramNode* NewVariable(
            char* variableName
        ) const;
    
        virtual ProgramNode* NewAssignment(
            ProgramNode* variable, ProgramNode* expression
        ) const;
    
        virtual ProgramNode* NewReturnStatement(
            ProgramNode* value
        ) const;
    
        virtual ProgramNode* NewCondition(
            ProgramNode* condition,
            ProgramNode* truePart, ProgramNode* falsePart
        ) const;
        // ...
    
        ProgramNode* GetRootNode();
    private:
        ProgramNode* _node;
    };
</PRE>

<A NAME="auto1048"></A>
<P>The parse tree is made up of instances of <CODE>ProgramNode</CODE>
subclasses such as <CODE>StatementNode</CODE>,
<CODE>ExpressionNode</CODE>, and so forth.  The <CODE>ProgramNode</CODE>
hierarchy is an example of the <A HREF="pat4cfs.htm" TARGET="_mainDisplayFrame">Composite&nbsp;(163)</A>
pattern. <CODE>ProgramNode</CODE> defines an interface for manipulating
the program node and its children, if any.</P>

<A NAME="auto1049"></A>
<PRE>
    class ProgramNode {
    public:
        // program node manipulation
        virtual void GetSourcePosition(int&amp; line, int&amp; index);
        // ...
    
        // child manipulation
        virtual void Add(ProgramNode*);
        virtual void Remove(ProgramNode*);
        // ...
    
        virtual void Traverse(CodeGenerator&amp;);
    protected:
        ProgramNode();
    };
</PRE>


<A NAME="visit-in-compiler"></A>
<P>The <CODE>Traverse</CODE> operation takes a <CODE>CodeGenerator</CODE>
object.  <CODE>ProgramNode</CODE> subclasses use this object to generate
machine code in the form of <CODE>Bytecode</CODE> objects on a
<CODE>BytecodeStream</CODE>.  The class <CODE>CodeGenerator</CODE> is a
visitor&nbsp;(see <A HREF="pat5kfs.htm" TARGET="_mainDisplayFrame">Visitor&nbsp;(331)</A>).</P>

<A NAME="auto1050"></A>
<PRE>
    class CodeGenerator {
    public:
        virtual void Visit(StatementNode*);
        virtual void Visit(ExpressionNode*);
        // ...
    protected:
        CodeGenerator(BytecodeStream&amp;);
    protected:
        BytecodeStream&amp; _output;
    };
</PRE>

<A NAME="auto1051"></A>
<P><CODE>CodeGenerator</CODE> has subclasses, for example,
<CODE>StackMachineCodeGenerator</CODE> and <CODE>RISCCodeGenerator</CODE>,
that generate machine code for different hardware architectures.</P>

<A NAME="auto1052"></A>
<P>Each subclass of <CODE>ProgramNode</CODE> implements <CODE>Traverse</CODE>
to call <CODE>Traverse</CODE> on its child <CODE>ProgramNode</CODE>
objects.  In turn, each child does the same for its children, and so
on recursively.  For example, <CODE>ExpressionNode</CODE> defines
<CODE>Traverse</CODE> as follows:</P>

<A NAME="auto1053"></A>
<PRE>
    void ExpressionNode::Traverse (CodeGenerator&amp; cg) {
        cg.Visit(this);
    
        ListIterator<ProgramNode*> i(_children);
    
        for (i.First(); !i.IsDone(); i.Next()) {
            i.CurrentItem()->Traverse(cg);
        }
    }
</PRE>

<A NAME="auto1054"></A>
<P>The classes we've discussed so far make up the compiler subsystem.
Now we'll introduce a <CODE>Compiler</CODE> class, a facade that puts all
these pieces together.  <CODE>Compiler</CODE> provides a simple interface
for compiling source and generating code for a particular machine.</P>

<A NAME="auto1055"></A>
<PRE>
    class Compiler {
    public:
        Compiler();
    
        virtual void Compile(istream&amp;, BytecodeStream&amp;);
    };
    
    void Compiler::Compile (
        istream&amp; input, BytecodeStream&amp; output
    ) {
        Scanner scanner(input);
        ProgramNodeBuilder builder;
        Parser parser;
    
        parser.Parse(scanner, builder);
    
        RISCCodeGenerator generator(output);
        ProgramNode* parseTree = builder.GetRootNode();
        parseTree->Traverse(generator);
    }
</PRE>

<A NAME="auto1056"></A>
<P>This implementation hard-codes the type of code generator to use so
that programmers aren't required to specify the target architecture.
That might be reasonable if there's only ever one target architecture.
If that's not the case, then we might want to change the
<CODE>Compiler</CODE> constructor to take a <CODE>CodeGenerator</CODE>
parameter.  Then programmers can specify the generator to use when
they instantiate <CODE>Compiler</CODE>.  The compiler facade can
parameterize other participants such as <CODE>Scanner</CODE> and
<CODE>ProgramNodeBuilder</CODE> as well, which adds flexibility, but it also
detracts from the Facade pattern's mission, which is to simplify the
interface for the common case.</P>

<A NAME="knownuses"><A>
<H2><A HREF="#relatedpatterns"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Known Uses</H2> 


<A NAME="auto1057"></A>
<P>The compiler example in the Sample Code section was inspired by the
ObjectWorks\Smalltalk compiler system&nbsp;[<A HREF="vfs.htm?doc=bib-0.htm&fid=bb&hid=parcplace_smalltalk" TARGET="_mainDisplayFrame">Par90</A>].</P>

<A NAME="et-use-facade"></A>
<P>In the ET++ application framework&nbsp;[<A HREF="vfs.htm?doc=bib-0.htm&fid=bb&hid=et++" TARGET="_mainDisplayFrame">WGM88</A>], an application can have
built-in browsing tools for inspecting its objects at run-time.  These
browsing tools are implemented in a separate subsystem that includes a
Facade class called "ProgrammingEnvironment."  This facade defines
operations such as InspectObject and InspectClass for accessing the
browsers.</P>

<A NAME="auto1058"></A>
<P>An ET++ application can also forgo built-in browsing support.  In
that case, ProgrammingEnvironment implements these requests as null
operations; that is, they do nothing.  Only the
ETProgrammingEnvironment subclass implements these requests with
operations that display the corresponding browsers.  The application
has no knowledge of whether a browsing environment is available or
not; there's abstract coupling between the application and the
browsing subsystem.</P>

<A NAME="domain"></A>
<A NAME="facade-use"></A>
<P>The Choices operating system&nbsp;[<A HREF="vfs.htm?doc=bib-0.htm&fid=bb&hid=choices_cacm" TARGET="_mainDisplayFrame">CIRM93</A>] uses facades to
compose many frameworks into one.  The key abstractions in Choices are
processes, storage, and address spaces.  For each of these
abstractions there is a corresponding subsystem, implemented as a
framework, that supports porting Choices to a variety of different
hardware platforms.  Two of these subsystems have a "representative"
(i.e., facade). These representatives are FileSystemInterface (storage)
and Domain (address spaces).</P>

<A NAME="facade-choices"></A>
<P ALIGN=CENTER><IMG SRC="Pictures/facad059.gif"></P>

<A NAME="virtual-memory"></A>
<P>For example, the virtual memory framework has Domain as its facade.  A
Domain represents an address space.  It provides a mapping between
virtual addresses and offsets into memory objects, files, or backing
store.  The main operations on Domain support adding a memory object
at a particular address, removing a memory object, and handling a page
fault.</P>

<A NAME="auto1059"></A>
<P>As the preceding diagram shows, the virtual memory subsystem uses the
following components internally:</P>

<UL>

<A NAME="auto1060"></A>
<LI>MemoryObject represents a data store.</LI>

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

<A NAME="strat-in-choices"></A>
<LI>MemoryObjectCache caches the data of MemoryObjects in physical memory.
MemoryObjectCache is actually a <A HREF="pat5ifs.htm" TARGET="_mainDisplayFrame">Strategy&nbsp;(315)</A> that
localizes the caching policy.</LI>

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

<A NAME="auto1063"></A>
<LI>AddressTranslation encapsulates the address translation hardware.</LI>

</UL>

<A NAME="auto1064"></A>
<P>The RepairFault operation is called whenever a page fault interrupt
occurs.  The Domain finds the memory object at the address causing the
fault and delegates the RepairFault operation to the cache associated
with that memory object.  Domains can be customized by changing their
components.</P>

<A NAME="relatedpatterns"></A>
<H2><A HREF="#last"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Related Patterns</H2> 

<A NAME="absfact"></A>
<P><A HREF="pat3afs.htm" TARGET="_mainDisplayFrame">Abstract Factory&nbsp;(87)</A>
can be used with Facade to provide an interface for creating
subsystem objects in a subsystem-independent way.  Abstract Factory
can also be used as an alternative to Facade to hide platform-specific
classes.</P>

<A NAME="facade-vs-med"></A>
<P><A HREF="pat5efs.htm" TARGET="_mainDisplayFrame">Mediator&nbsp;(273)</A> is
similar to Facade in that it abstracts functionality of existing
classes.  However, Mediator's purpose is to abstract arbitrary
communication between colleague objects, often centralizing
functionality that doesn't belong in any one of them.  A mediator's
colleagues are aware of and communicate with the mediator instead
of communicating with each other directly.  In contrast, a facade
merely abstracts the interface to subsystem objects to make them
easier to use; it doesn't define new functionality, and subsystem
classes don't know about it.</P>

<A NAME="auto1065"></A>
<P>Usually only one Facade object is required.  Thus Facade objects are
often <A HREF="pat3efs.htm" TARGET="_mainDisplayFrame">Singletons&nbsp;(127)</A>.</P>

<A NAME="last"></A>
<P><A HREF="#intent"><IMG SRC="gifsb/up3.gif" BORDER=0></A><BR>
<A HREF="pat4ffs.htm" TARGET="_mainDisplayFrame"><IMG SRC="gifsb/rightar3.gif"
	ALIGN=TOP BORDER=0></A> <A HREF="pat4ffs.htm"
	TARGET="_mainDisplayFrame">Flyweight</A><BR>
<A HREF="pat4dfs.htm" TARGET="_mainDisplayFrame"><IMG SRC="gifsb/leftarr3.gif"
	ALIGN=TOP BORDER=0></A> <A HREF="pat4dfs.htm"
	TARGET="_mainDisplayFrame">Decorator</A>
</P>

</BODY>

</HTML>

⌨️ 快捷键说明

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