代码之家  ›  专栏  ›  技术社区  ›  Adrian

如何设计对象以不同方式格式化文本

  •  0
  • Adrian  · 技术社区  · 6 年前

    我有一个项目,可以根据应用程序所处的某些状态和模式打印一些数据。

    enum Mode {
       mode1 = 0,
       mode2
    };
    
    enum State {
       state1 = 0,
       state2
    };
    

    数据可以以多种方式打印,以下是一些示例:

    1. name1 value1 name2 value2 name3 value3
    
    2. value1 value2 value3
    
    3. name1 : value1.  
       name2 : value2   
       name3 : value3  
    

    我试图用ostream操作符重载创建一个类:

    class Formater {
    public:
       Formater(.....) { ... } // pass name, value, mode, state here.
    
       virtual void print_State1_Mode1(ostream& os) { }
       virtual void print_State1_Mode2(ostream& os) { }
       virtual void print_State2_Mode1(ostream& os) { }
       virtual void print_State2_Mode2(ostream& os) { }
    
        friend std::ostream& operator << (std::ostream& os, const Formater& f) {
            if (state1 & mode1) {
                print_State1_Mode1(os);
            }
            else if(state1 & mode2) {
                print_State1_Mode2(os);
            }
            else if(state2 & mode1) {
                print_State2_Mode1(os);
            }
            else {
                print_State2_Mode2(os);
            }
    
            return os;
        } 
    };
    

    这将用于某些命令,根据状态和模式,每个命令都可以有不同的格式来打印文本。

    因此,如果我的对象不能满足命令,我将从它继承并创建一个新的命令,并重写其中一个虚拟方法,这取决于我需要新格式的模式和状态。

    因此,我最终可以得到更多的Formatter对象(Formatter1、Formatter2……)。

    我对这种方法不是百分之百满意。是否有人有更好的设计或我可以改进当前设计的方法?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Lingxi    6 年前

    我不明白为什么这个简单的设计还不够。

    class Formatter {
      ...
      virtual std::ostream& insert(std::ostream&) const = 0;
      friend std::ostream& operator<<(std::ostream& os, const Formatter& fmt) {
        return fmt.insert(os); 
      }
    };
    
    class Formatter_State1_Mode1: public Formatter {
      ...
      std::ostream& insert(std::ostream&) const override;
    };
    
    class Formatter_State1_Mode2: public Formatter {
      ...
      std::ostream& insert(std::ostream&) const override;
    };
    
    Formatter* makeFormatter(Mode, State, ...);
    

    它摆脱了丑陋的if-else阶梯,并产生了更好的性能。

        2
  •  0
  •   Ravindra Ranwala    6 年前

    我建议您使用 Bridge 此处为图案。因此,您的功能应该仔细分解为两部分。因此,您的状态应该是抽象或精炼的抽象。和 Formatter 将是 Implementor 。然后您可以使用不同的格式化程序 ConcreteImplementors 。您可以使用 AbstractFactory 说FormatterFactory,从一些config属性获取格式化程序。这种逻辑应该由你自己定义。

    这是 Bridge Pattern 定义依据 Gang of Four :将抽象与其实现解耦,以便两者可以独立变化。