设计模式?怎么做"抽象生成器创建抽象实例"

时间:2015-01-20 18:37:25

标签: c++ design-patterns

我有两个类层次结构:配置模板和配置实例。 配置模板可以生成配置实例。 示例:从一组可能的配置创建笔。后来我可能想要添加铅笔和标记,因此层次结构。

(注意:在下面的C ++ 11代码中,我跳过明显的包含,虚拟析构函数,"使用命名空间std"等等;示例和问题是关于抽象)

struct cConfigTemplate_WritingTool
{
    int length_range[2];
    string possible_shapes[] = {"circle", "octagon"};
};

struct cConfigInstance_WritingTool
{
    int length;
    string shape;
};

struct cConfigTemplate_Pen : public cConfigTemplate_WritingTool
{
    string ink_colours[] = {"red", "blue"};
    float chance_to_be_ball_point;
};

struct cConfigInstance_Pen : public cConfigInstance_WritingTool
{
    string ink_colour;
    bool is_ball_point;
};

我的问题是:

  • 这是一个很好的设计吗?我需要层次结构来添加共享参数的其他配置类型。
  • 如果设计不好,你会怎样做得更好?是否有我错过的设计模式?如果是,哪些以及如何应用?
  • 如何实现以抽象方式从cConfigTemplate_WritingTool生成cConfigInstance_WritingTool的功能?例如

    cConfigTemplate_WritingTool * tool_template = new cConfigTemplate_Pen(); cConfigInstance_WritingTool * tool_instance = tool_template->generate_instance();

1 个答案:

答案 0 :(得分:-2)

  

这是一个很好的设计吗?

是的,这是一个很好的设计,也不错,但是,可以做一些改进。我更喜欢使用" class"而不是" struct"。

<强>之前:

struct cConfigTemplate_WritingTool
{
  int length_range[2];
  string possible_shapes = {"circle", "octagon"};
};

<强>后:

public class cConfigTemplate_WritingTool
{
  public int length_range[2];
  public string possible_shapes = {"circle", "octagon"};
};

使用&#34; class&#34;时,您需要添加&#34; public&#34;关键字。

另一个一般性建议是,使用更有意义的标识符。

<强>之前:

struct cConfigTemplate_WritingTool
{
  int length_range[2];
  string possible_shapes = {"circle", "octagon"};
};

struct cConfigInstance_WritingTool
{
  public int length;
  public string shape;
};

<强>后:

struct TemplateClass
{
  int length_range[2];
  string possible_shapes = {"circle", "octagon"};
};

struct ToolClass
{
  int length;
  string shape;
};

Altought,这不是一个要求,使用更有意义的标识符,有助于描述您脑海中的问题,现实世界,程序/源代码。


  

如果设计不好,你会怎样做得更好?

也许你过早地抽出超级课程,并试图在当时完成整个课程。

在设计层次结构时,您可能希望以相反的方式开始。首先设计&#34; leaf&#34;或者&#34;孩子&#34;课程,没有&#34;超级&#34;课程,以及后来的超级&#34;类。

以下代码示例不是完全C ++程序。一些代码已被省略,以便做出明确的答案。


[1]您想设计一个WritingTool应用程序。

注意,添加一个&#34; Universe&#34;非常常见。或者&#34;应用程序&#34;包装整个程序的对象。

public /* concrete */ class WritingToolClass
{
  public:
    void Write() { ... }
} // class WritingToolClass

int main()
{
   WritingToolClass MyWritingTool = new WritingToolClass();

   MyWritingTool->Write();

   free MyWritingTool();
} // int main(...)

[2]在此应用程序中,用户将使用具有预定义功能的多个工具。因此,工具是对象,具有类定义。工具的例子有&#34; Pen&#34;,&#34;图&#34;,&#34;刷&#34;等

public /* concrete */ class WritingToolClass
{
  public:
    void Write() { ... }
} // class WritingToolClass

public /* concrete */ class PenClass
{
  public:
    void Write() { ... }
} // class PenClass

public /* concrete */ class BrushClass
{
  public:
    void Write() { ... }
} // class BrushClass

int main()
{
   WritingToolClass MyWritingTool = new WritingToolClass();

   MyWritingTool->Write();

   free MyWritingTool();
} // int main(...)

[3]这些工具具有在创建时分配的属性。

...

public /* concrete*/ class PenClass
{
  protected:
    ColorType Color;
    int Width;
  public:
    /* constructor */ PenClass
      (ColorType AColor, int AWidth) 
        {
          this.Color = AColor;
          this.Width = AWidth;
        }
} // class PenClass

public /* concrete */ class BrushClass
{
  protected:
    ColorType Color;
  public:
    /* constructor */ PenClass
      (ColorType AColor) 
        {
          this.Color = AColor;
        }
} // class BrushClass

...

[4]为了创建具有给定功能的工具,应用程序有一些特殊的对象,就像&#34;工具&#34;的工厂。

让他们称呼他们&#34;模板&#34;。对于每种类型的工具,您都需要一个特定的&#34;模板&#34;或&#34;工厂&#34;。

该模板将使用名为&#34; generateInstance&#34;的函数为您提供特定工具:

...

public /* concrete */ class PenClass
{
  // ...
} // class PenClass

public /* concrete */ class PenTemplateClass
{
  public:
    PenClass generateInstance() { ... }
} // class PenTemplateClass

public /* concrete */ class BrushClass
{
  // ...
} // class BrushClass

public /* concrete */ class BrushTemplateClass
{
  public:
    BrushClass generateInstance() { ... }
} // class BrushTemplateClass

...

检查&#34; generateInstance&#34;每个模板的功能返回不同的类型。这将在以后改变。


[5]&#34;工具&#34;是独立的,没有相关的,具体的(不是抽象的)类。在示例中,它有几个重复的成员,其中一些被省略。让我们为他们添加一个抽象超类。

...

public /* abstract */ class ToolClass
{
  /* replaceable */ virtual void Draw() { ... }
} // class ToolClass

public /* concrete */ class PenToolClass: public ToolClass
{
  /* replaced */ virtual void Draw() { ... }
} // class PenToolClass

public /* concrete */ class BrushToolClass: public ToolClass
{
  /* replaced */ virtual void Draw() { ... }
} // class BrushToolClass

public /* concrete */ class FontToolClass: public ToolClass
{
  /* replaced */ virtual void Draw() { ... }
} // class FontToolClass

...

检查PenClass是否已重命名为PenToolClass,其他工具也是如此。

我们甚至添加一个新的&#34; FontToolClass&#34;类。所以,我们现在有一个小小的&#34;工具&#34;类层次结构。


[6]同样适用于&#34;工具&#34; (s)名为&#34; Template&#34; (S)。让我们添加一个抽象类,其代码由具体的&#34;模板&#34;继承。 (一个或多个)。

public /* abstract */ class ToolClass
{
  // ...
} // class ToolClass

public /* abstract */ class TemplateClass
{
  public:
    /* replaceable */ virtual ToolClass generateInstance() { ... }
} // class TemplateClass

public /* concrete */ class PenTemplateClass: public TemplateClass
{
  public:
    /* replaced */ virtual ToolClass generateInstance() { ... }
} // class PenTemplateClass

public /* concrete */ class BrushTemplateClass: public TemplateClass
{
  public:
    /* replaced */ virtual ToolClass generateInstance() { ... }
} // class BrushTemplateClass

public /* concrete */ class FontTemplateClass: public TemplateClass
{
  public:
    /* replaced */ virtual ToolClass generateInstance() { ... }
} // class FontTemplateClass

注意,&#34;模板&#34;的基类(s)现在,有一个generateInstance函数,即virtual,并返回ToolClass

并且,具体的&#34;模板&#34;中替换的generateInstance函数(s)类也返回一个抽象类型,但是,在现实世界中,它应该返回匹配&#34;工具&#34;类。

  

我是否错过了这种设计模式?如果是,那么它将如何应用?

注意:前面的例子被称为&#34;工厂&#34;软件设计模式。


  

如何实现生成功能的功能   来自cConfigTemplate_WritingTool的cConfigInstance_WritingTool   抽象的方式?

[7]首先,这是通过在&#34;模板&#34;中定义virtual(&#34;可替换&#34;)功能来完成的。 (s)基础。

public /* abstract */ class TemplateClass
{
  public:
    /* replaceable */ virtual ToolClass generateInstance() = 0;
} // class TemplateClass

= 0表示此函数没有代码,并且打算在子类中替换。


[8]并取代新的&#34;虚拟&#34;函数在&#34;模板&#34;的子类中(s)课程。

public /* concrete */ class PenToolTemplateClass: public TemplateClass
{
  public:
    ColorType Color;
    int Width;
  public:
    /* replaced */ virtual ToolClass generateInstance()
    {
      PenClass Result = new PenClass(this.Color, this.Width);
      return Result;
    }
} // class PenToolTemplateClass

public /* concrete */ class BrushToolTemplateClass: public TemplateClass
{
  public:
    /* replaced */ virtual ToolClass generateInstance()
    {
      // ...
    }
} // class BrushToolTemplateClass

public /* concrete */ class FontToolTemplateClass: public TemplateClass
{
  public:
    /* replaced */ virtual ToolClass generateInstance()
    {
      // ...
    }
} // class FontToolTemplateClass

public /* concrete */ class WritingToolClass
{
  public:
    void Write()
    {
      PenTemplateClass MyPenTemplate = new PenTemplateClass();

      MyPenTemplate.Color = Blue;
      MyPenTemplate.Width = 1;
      PenToolClass MyBluePen = MyPenTemplate->generateInstance();
        MyBluePen.Write();
      free MyBluePen();

      MyPenTemplate.Color = Red;
      MyPenTemplate.Width = 2;
      PenToolClass MyRedPen = MyPenTemplate->generateInstance();
        MyRedPen.Write();
      free MyRedPen();

      MyBrushTemplate.Color = Green;
      BrushToolClass MyGreenBrush = MyPenTemplate->generateInstance();
        MyGreenBrush.Write();
      free MyGreenBrush();

      // and so on

      free MyPenTemplate();
    } // void Write(...)
} // class WritingToolClass

int main()
{
   WritingToolClass MyWritingTool = new WritingToolClass();

   MyWritingTool->Write();

   free MyWritingTool();
} // int main(...)

设计类层次结构并非易事。以前的C ++示例并不完整,只是给出了问题的一般理想。

干杯。