我有两个类层次结构:配置模板和配置实例。 配置模板可以生成配置实例。 示例:从一组可能的配置创建笔。后来我可能想要添加铅笔和标记,因此层次结构。
(注意:在下面的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();
答案 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 ++示例并不完整,只是给出了问题的一般理想。
干杯。