使用原型模式动态配置应用程序
configuring app dynamically using prototype pattern
我正在阅读 GoF 书中关于原型模式的内容。这是文本片段
Configuring an application with classes dynamically: Some runtime
environments let you load classes into an application dynamically. The
prototype pattern is the key to exploiting such facilities in a
language like C++.
An application that wants to create instances of a dynamically loaded
classes won't be able to reference its constructor statically.
Instead, runtime environment creates an instance of each class
automatically when it's loaded, and registers with a prototype
manager. Then the application can ask the prototype manager for newly
loaded classes, classes that weren't ;omled with the program orginally
以上问题
作者所说的 "An application that wants to create instances of a dynamically loaded classes won't be able to reference its constructor statically" 是什么意思?例如,如果我们使用动态 link 库,我仍然可以使用 new 创建对象,那么作者所说的我们将无法静态引用构造函数是什么意思?
请求举例说明如何使用原型模式来动态利用加载 类 应用程序。
我的 50 美分:
- 我相信作者指的是符号库中没有 class 定义的情况,但是你想实例化对象,并将它们传递给库消费者函数(所以你是内存所有者,共享库是消费者,但您无权访问库中的具体 classes )
示例(我会从头开始写一个来强调一个有用的场景,然后我会写另一个我实际遇到的)
有了动态库 TextEditorWidgets.dll 和您的主应用程序,TextEditorWidget 公开了一个抽象原型 TEWPrototype 和一个根据字符串标识符获取特定原型的工厂方法。
将工厂方法从定义为 :
的 dll 公开
TEWPrototype* TEWPrototype::getPrototypeFor(string identifier)
{
TEWPrototype* result;
if (identifier == "SomeWidget")
{
result = ConcreteSomeWidgetPrototype;
} else if ...
return result;
}
在您的应用程序中,您可以使用以下代码:
{
vector<TEWPrototype*> allocatedWidgets;
...
TEWPrototype* SomeWidget = TEWPrototype::getPrototypeFor("SomeWidget").clone();// you are now the memory owner
allocatedWidgets.push_back(SomeWidget); // keep for deletion
TextEditorWidgetsHandle->doSomethingWithTheWidget(SomeWidget);// pass the instantiation to the consumer who knows the widget full definition
}
在上面的示例中,作为应用开发者,您有以下优点:
- 您将控制 dll 分配的内容、时间和方式
- 您将控制在应用程序的整个生命周期内是否删除小部件
作为 dll 开发人员的专家:
- 您将能够在提供向后功能的同时添加新的小部件
- 您可以保证没有人会在 .dll 之外使用您的内部小部件功能
实际例子:
在开发游戏时,游戏开发团队创建了新实体,我们需要一种快速的方法来为设计师提供新对象,供他们添加到游戏场景中。我们有自己的内部编辑器,所以我们可以控制设计工具。
方法是让世界编辑器加载 .dll,然后在编辑器菜单中显示加载到 dll 中的对象。编辑器不知道 dll 中有什么 classes,它只知道它们有一个 draw 和一个 setPosition 函数(以及其他一些东西)。
加载 dll 时,在编辑器中,对象的名称被添加到对象原型管理器中(基本上我们有一个静态函数 getAvailableObjects 并且在加载 dll 之后,我们会查询它以获取字符串).
当设计人员从菜单中选择一个对象(比如说 Crate)时,就会创建该对象的一个新实例,该实例将在编辑器中绘制,并且设计人员可以四处移动它。
编辑器无法自行实例化对象,因为他对对象的大小及其构造函数一无所知。然而,我们为每种类型预先实例化了对象,每次艺术家选择创建一个 "new" Crate 时,这些对象都会被克隆。
预览中也使用了预先实例化的对象。
当开发团队发布一组新的实体时,我们只是将新的 dll 提供给设计师,他们只需要 "refresh" 编辑器一个 BOOM:奇迹发生了:菜单中的新对象.
作为替代方案,抽象工厂可以提供类似的功能。
我正在阅读 GoF 书中关于原型模式的内容。这是文本片段
Configuring an application with classes dynamically: Some runtime environments let you load classes into an application dynamically. The prototype pattern is the key to exploiting such facilities in a language like C++.
An application that wants to create instances of a dynamically loaded classes won't be able to reference its constructor statically. Instead, runtime environment creates an instance of each class automatically when it's loaded, and registers with a prototype manager. Then the application can ask the prototype manager for newly loaded classes, classes that weren't ;omled with the program orginally
以上问题
作者所说的 "An application that wants to create instances of a dynamically loaded classes won't be able to reference its constructor statically" 是什么意思?例如,如果我们使用动态 link 库,我仍然可以使用 new 创建对象,那么作者所说的我们将无法静态引用构造函数是什么意思?
请求举例说明如何使用原型模式来动态利用加载 类 应用程序。
我的 50 美分:
- 我相信作者指的是符号库中没有 class 定义的情况,但是你想实例化对象,并将它们传递给库消费者函数(所以你是内存所有者,共享库是消费者,但您无权访问库中的具体 classes )
示例(我会从头开始写一个来强调一个有用的场景,然后我会写另一个我实际遇到的)
有了动态库 TextEditorWidgets.dll 和您的主应用程序,TextEditorWidget 公开了一个抽象原型 TEWPrototype 和一个根据字符串标识符获取特定原型的工厂方法。
将工厂方法从定义为 :
的 dll 公开TEWPrototype* TEWPrototype::getPrototypeFor(string identifier) { TEWPrototype* result; if (identifier == "SomeWidget") { result = ConcreteSomeWidgetPrototype; } else if ... return result; }
在您的应用程序中,您可以使用以下代码:
{ vector<TEWPrototype*> allocatedWidgets; ... TEWPrototype* SomeWidget = TEWPrototype::getPrototypeFor("SomeWidget").clone();// you are now the memory owner allocatedWidgets.push_back(SomeWidget); // keep for deletion TextEditorWidgetsHandle->doSomethingWithTheWidget(SomeWidget);// pass the instantiation to the consumer who knows the widget full definition }
在上面的示例中,作为应用开发者,您有以下优点:
- 您将控制 dll 分配的内容、时间和方式
- 您将控制在应用程序的整个生命周期内是否删除小部件
作为 dll 开发人员的专家:
- 您将能够在提供向后功能的同时添加新的小部件
- 您可以保证没有人会在 .dll 之外使用您的内部小部件功能
实际例子:
在开发游戏时,游戏开发团队创建了新实体,我们需要一种快速的方法来为设计师提供新对象,供他们添加到游戏场景中。我们有自己的内部编辑器,所以我们可以控制设计工具。
方法是让世界编辑器加载 .dll,然后在编辑器菜单中显示加载到 dll 中的对象。编辑器不知道 dll 中有什么 classes,它只知道它们有一个 draw 和一个 setPosition 函数(以及其他一些东西)。
加载 dll 时,在编辑器中,对象的名称被添加到对象原型管理器中(基本上我们有一个静态函数 getAvailableObjects 并且在加载 dll 之后,我们会查询它以获取字符串).
当设计人员从菜单中选择一个对象(比如说 Crate)时,就会创建该对象的一个新实例,该实例将在编辑器中绘制,并且设计人员可以四处移动它。
编辑器无法自行实例化对象,因为他对对象的大小及其构造函数一无所知。然而,我们为每种类型预先实例化了对象,每次艺术家选择创建一个 "new" Crate 时,这些对象都会被克隆。
预览中也使用了预先实例化的对象。
当开发团队发布一组新的实体时,我们只是将新的 dll 提供给设计师,他们只需要 "refresh" 编辑器一个 BOOM:奇迹发生了:菜单中的新对象.
作为替代方案,抽象工厂可以提供类似的功能。