I am reading about prototype pattern by GoF book. Here is the text snippet
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
My questions on above
What does author mean by "An application that wants to create instances of a dynamically loaded classes won't be able to reference its constructor statically" ? For example if we use dynamic link library I can still create object using new so what does author mean by we won't be able to reference constructor statically?
Request to give an example how prototype pattern is used to exploit load classes application dynamically.
My 50 cents on this :
Example ( I will write one from the top of my head to underline a scenario where it would be useful then I will write another one that I actually bumped into)
Having a dynamic library TextEditorWidgets.dll and your main application , the TextEditorWidget exposes an abstract prototype TEWPrototype , and a factory method of getting certain prototypes according to let's say a string identifier.
Having the factory method exposed from the dll defined as :
TEWPrototype* TEWPrototype::getPrototypeFor(string identifier)
{
TEWPrototype* result;
if (identifier == "SomeWidget")
{
result = ConcreteSomeWidgetPrototype;
} else if ...
return result;
}
Inside your application you can use the following code :
{
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
}
In the example above you have the following pros as the app develoer :
The pros as the dll developer :
Practical example :
While working on a game , new entities were created by the game development team, and we needed a fast way to give the Designers the new objects for them to add into the game scene. We had our own in house editor, so we had control over the design tool.
The approach was to have the World Editor load .dlls , then expose in the editor menus what objects were loaded in the dlls. The editor didn't know what classes were inside the dlls, it only knew about them having a draw and a setPosition function (and some other things).
When the dll was loaded , inside the editor, the name of the object was added into an object prototype manager (basically we had a static function getAvailableObjects and after dll load, we would query that in order to get the strings).
When a Designer was choosing from a menu an object (let's say for example Crate), then a new instance of that object was created that was drawn inside the editor , and the designer could move it around.
The editor couldn't instantiate the object by itself because he knew nothing about the size of the object nor about his constructor. However we had pre-instantiated objects for each type, that were getting cloned each time the Artist chosed to create a "new" Crate.
The preinstantiated objects were also used in the preview .
When the development team released a new set of entities , we just provided the new dll to the Designers, and they would only need to "refresh" the editor an BOOM : magic happened : new objects in the menu .
As an alternative, an abstract factory can provide kind of the same functionality.