C++11访问者模式展示

2021-07-18  本文已影响0人  FredricZhu

题目


image.png

题目作者把accept和visit方法写反了,但是这不影响做题。
你也反着写就行了。
就是看着有点别扭。
这里的实现方式是传统的双向转发方式。
就是每个被访问对象有一个accept方法,接收访问者的访问。
访问对象有一堆visit方法,可以访问各种对象。[我是按正常的思路来说的,和代码刚好相反。]
这是这23种中最复杂的一个模式了。
因为它涉及到类层级的遍历。

程序代码如下,

#include <string>
#include <sstream>
using namespace std;

struct Value;
struct AdditionExpression;
struct MultiplicationExpression;

struct ExpressionVisitor
{
   virtual void accept(Value& e) = 0;
   virtual void accept(AdditionExpression& ae) = 0;
   virtual void accept(MultiplicationExpression& me) = 0;
};

struct Expression
{
  virtual void visit(ExpressionVisitor& ev) = 0;
};

struct Value : Expression
{
  int value;

  Value(int value) : value(value) {}
  
  void visit(ExpressionVisitor& ev) {
      ev.accept(*this);
  }
};

struct AdditionExpression : Expression
{
  Expression &lhs, &rhs;

  AdditionExpression(Expression &lhs, Expression &rhs) : lhs(lhs), rhs(rhs) {}
  
  void visit(ExpressionVisitor& ev) {
      ev.accept(*this);
  }
};

struct MultiplicationExpression : Expression
{
  Expression &lhs, &rhs;

  MultiplicationExpression(Expression &lhs, Expression &rhs)
    : lhs(lhs), rhs(rhs) {}
    
  void visit(ExpressionVisitor& ev) {
      ev.accept(*this);
  }
};

struct ExpressionPrinter : ExpressionVisitor
{
   void accept(Value& e) override {
       oss << e.value;    
   }
   
   // 所有加法都需要()
   void accept(AdditionExpression& ae) override {
       oss << "(";
       ae.lhs.visit(*this);
       oss << "+";
       ae.rhs.visit(*this);
       oss << ")";
   }
   
   // 乘法只有右值是加法的时候需要()
   void accept(MultiplicationExpression& me) override {
       bool need_braces = (typeid(me.rhs) == typeid(AdditionExpression));
       if(need_braces) oss << "(";
       me.lhs.visit(*this);
       oss << "*";
       me.rhs.visit(*this);
       if(need_braces) oss << ")";
   }
    

  string str() const { 
        return oss.str();
  }
  
  private:
    ostringstream oss;
};
上一篇下一篇

猜你喜欢

热点阅读