+ 2

Prototype pattern

Hi Is my implementation of prototype correct ? Also another question is on need of the same. Is calling constructor expensive compared to copy constructor? If so, why don't we opt for the same always ? https://code.sololearn.com/cEJc31Teaiw6/?ref=app

27th Mar 2021, 3:15 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
7 ответов
+ 2
Yes, your prototypes for methods in the Test class look fine. Consider this minor improvement. If you want to let more of your methods work on const instances of Test, you could make your print method const since it shouldn't have any side effects on your Test instance. For example, void print() const; Also: void Test::print() const {... No, a copy-constructor isn't necessarily much faster than any other kind of constructor. The expense of calling one constructor vs another depends completely on how you implement each. Copy constructors are often quite fast since their jobs are simply to copy the instance passed into it. Any other constructor that takes different arguments but does similar work will take similar time.
27th Mar 2021, 8:42 PM
Josh Greig
Josh Greig - avatar
+ 1
You can call a constructor if you know what class you want your instance to be made of. If you know your variable is of class A and not a subclass of A, you could call A's copy constructor to get your clone and clone would be useless for that case. What if you know that your variable is of type A but you're not sure what subclass it belongs to? That's closer to the problem that prototype design pattern solves. There are many ways to implement the prototype pattern but your clone method looks very nice and simple. If you had more subclasses, you should also make it virtual like this: virtual shared_ptr <Test> clone() const; More detail on "virtual" is at: https://en.cppreference.com/w/cpp/language/virtual Let's say you had a class Test, TestSubclassA that inherits Test, and TestSubclassB that also inherits from Test. Making clone virtual in the Test class will mean that every instance of your superclass or base class would have a pointer to the method's implementation. Let's say you had a variable named x of type Test and you called x.clone(), either TestSubclassA or TestSubclassB's clone implementation will run and create a new instance of those classes while copying appropriately. In other words, the inner workings of "virtual" will solve the problem of identifying which subclass's clone method to run and an instance of the most appropriate subclass will get returned.
29th Mar 2021, 12:35 AM
Josh Greig
Josh Greig - avatar
+ 1
Does this clear it up? https://sharetext.me/gei8qxmt1m That runs in Sololearn's Code Playground but I didn't want to publish it on Sololearn since it is mostly your code. I didn't paste directly here since it is longer than Sololearn's limit of 2000 characters per answer. Start by checking the main function to quickly see what I changed. The problem solved by the prototype pattern is copying objects and especially when the specific class may be a subclass of the variable you're dealing with. I tried to clarify that by making a copy of a copy in the code shared above. The copy1 is obviously a Test pointer. It isn't so clear looking at: shared_ptr<Test> copy2 = copy1->clone(); that copy2 will become an instance of TestSubclassA but that's what happens because clone is virtual. If the clone method wasn't virtual, the clone result would be an instance of Test instead of the subclass. Wikipedia says: The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to: - avoid subclasses of an object creator in the client application, like the factory method pattern does. - avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) when it is prohibitively expensive for a given application. https://en.wikipedia.org/wiki/Prototype_pattern
29th Mar 2021, 10:25 PM
Josh Greig
Josh Greig - avatar
+ 1
Katan wrote, "Does this not create a new object? Prototype is not just giving us copy of already available instance to save time for recreating heavy objects again and again?" Response: Yes, that code created a new instance. If you just wanted another reference to the same object, you can use references or pointers and don't need the prototype pattern. If you're familiar with other design patterns, you'll know that the most important thing is to understand the pattern's problem and generally how to solve it. There are usually many small variations on how the problem can be solved while still applying the design pattern. Like other design patterns, the prototype pattern isn't specific to c++. Java standardized its clone method into every class. If you want to see another implementation of the prototype pattern in c++, check this example. It is near the bottom of the following page under the heading "14.12: Virtual constructors": https://fbb-git.gitlab.io/cppannotations/cppannotations/html/cplusplus14.html There are many ways to implement the prototype pattern and the above example works a slightly different way. - It uses regular pointers instead of shared_ptr. - Our code's Test is like this other example's base and Clonable class mixed together. - Our TestSubclassA class is like their Derived1. In their example, they have both a clone and a newCopy function which serve roughly the same purpose. You can see how they made newCopy virtual for the same reason we made clone virtual.
30th Mar 2021, 6:00 AM
Josh Greig
Josh Greig - avatar
0
Thanks Josh Greig ... I updated code with const.. "Any other constructor that takes different arguments but does similar work will take similar time." Now that's exactly what my query is. If parametric constructor and copy constructor in case of shallow copy take same time , then why to opt prototype pattern ? What benifit we are getting by this pattern ? Obviously for resources utilising class , deep copy is required and hence I belive prototype is not a choice at all. In case of shallow copy, copy constructor and parametric constructor perform with same speed so what's there to choice prototype pattern?
28th Mar 2021, 5:16 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
I am getting your points Josh Greig , but just one doesnot know which object it is makes unnecessary usage of virtual overhead... Still atleast some thing I got useful compared to my simple example. Still I belive that this pattern is not something which interested me more... May be still I am missing something or is it like this only ? Additionally , I tried to implement what you are saying with one base and one derived class as below : But implementation is not successful due to problem of covariant return type arises due to virtual with shared_ptr... However , I tried with reference wrapper and const cast with reference to class objects... Seems output is not yet as expected. Don't know why first copy is not calling print method displaying int as well. Thanks again for your time and effort to make me understand. https://code.sololearn.com/c1a2573A17A1/?ref=app
29th Mar 2021, 8:53 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
Thanks a lot... I have a question. shared_ptr<Test> TestSubclassB::clone() const { return shared_ptr<Test>(new TestSubclassB(A, F)); } Does this not create a new object? Prototype is not just giving us copy of already available instance to save time for recreating heavy objects again and again?
30th Mar 2021, 5:21 AM
Ketan Lalcheta
Ketan Lalcheta - avatar