设计模式?如何做"Abstract generator creating abstract instance"
Design pattern? How to do "Abstract generator creating abstract instance"
我有两个类层次结构:配置模板和配置实例。配置模板可以生成配置实例。示例:从一组可能的配置创建笔。稍后我可能想添加铅笔和记号笔,因此层次结构。
(注意:在下面的 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();
这是一个好的设计吗?
是的,这是一个很好的设计,还不错,但是,可以做一些改进。我更喜欢使用"类"而不是"结构"。
以前:
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"};
};
使用"类"时,需要添加"public"关键字。
另一个一般建议是使用更有意义的标识符。
以前:
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,这不是一个要求,使用更有意义的标识符,有助于描述您脑海中的问题,进入现实世界,程序/源代码。
如果这是一个糟糕的设计,你会如何做得更好?
也许你太早急于抽象超级类,并试图在当时做整个程序。
在设计层次结构时,您可能希望以相反的方式开始。首先设计没有"超"类的"叶"或"子"类,然后设计"超"类。
下面的代码示例不是完全C++程序。为了明确答案,省略了一些代码。
[1] 你想设计一个写作工具应用程序。
请注意,添加包装整个程序的"Universe"或"Application"对象是很常见的。
public /* concrete */ class WritingToolClass
{
public:
void Write() { ... }
} // class WritingToolClass
int main()
{
WritingToolClass MyWritingTool = new WritingToolClass();
MyWritingTool->Write();
free MyWritingTool();
} // int main(...)
[2] 在此应用程序上,用户将使用几个具有预定义功能的工具。工具是对象,因此具有类定义。工具的示例包括"笔"、"图形"、"画笔"等。
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] 为了创建具有给定功能的工具,应用程序具有一些特殊对象,这些对象类似于"工具"的工厂。
让我们称它们为"模板"。 对于每类工具,您都需要一个特定的"模板"或"工厂"。
该模板将为您提供一个特定的工具,使用一个名为"generateInstance"的函数:
...
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
...
检查每个模板的"生成实例"函数是否返回不同的类型。这将在以后改变。
[5] "工具"是独立的,不相关的,具体的(不是抽象的)类。在示例中,它有几个重复的成员,其中一些被省略了。让我们为它们添加一个抽象的超类。
...
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
,其他工具也是如此。
我们甚至添加了一个新的"FontToolClass"类。因此,我们现在有一个小的"工具"类层次结构。
[6] 同样适用于称为"模板"的"工具"工厂。让我们添加一个抽象类,其中包含由具体的"模板"继承的代码。
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
请注意,"模板"的基类现在有一个generateInstance
函数,即 virtual
,并返回一个ToolClass
。
并且,具体"模板"类中被替换的generateInstance
函数也返回抽象类型,但在现实世界中,它应该返回与"工具"类匹配的函数。
有没有我错过的设计模式?如果是,它如何应用?
注意:前面的示例称为"工厂"软件设计模式。
如何实现功能以生成 从cConfigTemplate_WritingTool cConfigInstance_WritingTool 抽象的方式?
[7] 首先,这是通过在"模板"基类中定义一个virtual
("可替换")函数来完成的。
public /* abstract */ class TemplateClass
{
public:
/* replaceable */ virtual ToolClass generateInstance() = 0;
} // class TemplateClass
= 0
表示此函数没有代码,旨在在子类中替换。
[8] 并在"模板"类的子类中替换一个新的"虚拟"函数。
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++的例子并不完整,只是给出你的问题的大致理想。
干杯。
- 如何理解"abstract-declarator containing an ellipsis shall only be used in a parameter-declaration"
- C++ "'Shape': cannot instantiate abstract class"找不到问题的根源
- Creating QGenericArgument
- Creating C++ API Library
- 让编译器告诉哪些方法不具体,而不是错误'invalid new-expression of abstract class type'
- CRTP - 静态接口中的"abstract"方法
- "Error creating variant or safe array" in TClientDataSet.LoadFromStream() in Delphi
- creating libraries
- "Allocating an object of abstract class type"错误,尽管所有函数都有实现
- Qt: Creating a QDoubleSlider
- Creating PointCloud from std::vector
- IDL 接口,C++,CORBA,我正在处理"conflicting return type specified for"和"invalid abstract return type for memb
- 我们可以通过在C++中的类中使用关键字“abstract”使所有方法抽象来声明接口类吗
- 抽象类和虚方法问题:"cannot allocate an object of abstract type"
- 设计模式?如何做"Abstract generator creating abstract instance"
- 启动 VirtualBoxSDK 测试应用程序返回错误"Error creating virtual box instance"
- 简洁的"this class overrides all necessary methods to be non-abstract"
- 'Cannot instantiate abstract class'虽然类不应该是抽象的
- 内存更贵。 "creating and deleting objects"还是"reusing a object"?
- 在类名后使用 MSVCC 扩展关键字"abstract"是一种好的做法吗?