笔记:Gof设计模式--Façade

本文介绍Facade设计模式,旨在为复杂的子系统提供一个简单的统一接口。通过使用Facade模式,可以降低客户端与子系统之间的耦合度,并简化子系统间的依赖关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、意图

  Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

2、适应性

Use the Facade pattern when

  •  you want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the subsystem more reusable and easier to customize, but it also becomes harder to use for clients that don't need to customize it. A facade can provide a simple default view of the subsystem that is good enough for most clients. Only clients needing more customizability will need to look beyond the facade.

  •  there are many dependencies between clients and the implementation classes of an abstraction. Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting subsystem independence and portability.
  •  you want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, then you can simplify the dependencies between them by making them communicate with each other solely through their facades.

 

3、结构

 

4、示例代码

  The Scanner class takes a stream of characters and produces a stream of tokens, one token at a time.

  class Scanner { 
    public: 
        Scanner(istream&); 
        virtual ~Scanner(); 
     
        virtual Token& Scan(); 
    private: 
        istream& _inputStream; 
    }; 

  The class Parser uses a ProgramNodeBuilder to construct a parse tree from a Scanner's tokens.

 class Parser { 
    public: 
        Parser(); 
        virtual ~Parser(); 
     
        virtual void Parse(Scanner&, ProgramNodeBuilder&); 
    }; 

 

Parser calls back on ProgramNodeBuilder to build the parse tree incrementally. These classes interact according to the Builder (110) pattern.

 class ProgramNodeBuilder { 
 public: 
        ProgramNodeBuilder(); 
     
        virtual ProgramNode* NewVariable( 
            const 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; 
    }; 


  The parse tree is made up of instances of ProgramNode subclasses such as StatementNode, ExpressionNode, and so forth. The ProgramNode hierarchy is an example of the Composite (183) pattern. ProgramNode defines an interface for manipulating the program node and its children, if any.

 class ProgramNode { 
    public: 
        // program node manipulation 
        virtual void GetSourcePosition(int& line, int& index); 
        // ... 
     
        // child manipulation 
        virtual void Add(ProgramNode*); 
        virtual void Remove(ProgramNode*); 
        // ... 
     
        virtual void Traverse(CodeGenerator&); 
 protected: 
        ProgramNode(); 
    }; 


The Traverse operation takes a CodeGenerator object. ProgramNode subclasses use this object to generate machine code in the form of Bytecode objects on a BytecodeStream. The class CodeGenerator is a visitor (see Visitor (366)).

 class CodeGenerator { 
    public: 
        virtual void Visit(StatementNode*); 
        virtual void Visit(ExpressionNode*); 
        // ... 
    protected: 
        CodeGenerator(BytecodeStream&); 
    protected: 
        BytecodeStream& _output; 
    }; 


  CodeGenerator has subclasses, for example, StackMachineCodeGenerator and RISCCodeGenerator, that generate machine code for different hardware architectures.
  Each subclass of ProgramNode implements Traverse to call Traverse on its child ProgramNode objects. In turn, each child does the same for its children, and so on recursively. For example, ExpressionNode defines Traverse as follows.

 void ExpressionNode::Traverse (CodeGenerator& cg) { 
        cg.Visit(this); 
     
        ListIterator i(_children); 
     
        for (i.First(); !i.IsDone(); i.Next()) { 
            i.CurrentItem()->Traverse(cg); 
        } 
    }

 

 The classes we've discussed so far make up the compiler subsystem. Now we'll introduce a Compiler class, a facade that puts all these pieces together. Compiler provides a simple interface for compiling source and generating code for a particular machine.

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



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值