From 57f7c392e87f96d3c836e29b6d11955a052d6ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 18 May 2024 08:12:18 +0300 Subject: [PATCH] docs: update prototype --- prototype/README.md | 82 ++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/prototype/README.md b/prototype/README.md index 180dd7fd2..2e2078651 100644 --- a/prototype/README.md +++ b/prototype/README.md @@ -3,24 +3,25 @@ title: Prototype category: Creational language: en tag: - - Gang Of Four - - Instantiation + - Gang Of Four + - Instantiation + - Object composition + - Polymorphism --- +## Also known as + +* Clone + ## Intent -Specify the kinds of objects to create using a prototypical instance, and create new objects by -copying this prototype. +The Prototype pattern is used to specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. ## Explanation -First, it should be noted that the Prototype pattern is not used to gain performance benefits. It's only -used for creating new objects from prototype instances. - Real-world example -> Remember Dolly? The sheep that was cloned! Let's not get into the details but the key point here is -> that it is all about cloning. +> Remember Dolly? The sheep that was cloned! Let's not get into the details but the key point here is that it is all about cloning. In plain words @@ -28,18 +29,11 @@ In plain words 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. - -In short, it allows you to create a copy of an existing object and modify it to your needs, instead -of going through the trouble of creating an object from scratch and setting it up. +> 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. **Programmatic Example** -In Java, the prototype pattern is recommended to be implemented as follows. First, create an -interface with a method for cloning objects. In this example, `Prototype` interface accomplishes -this with its `copy` method. +In Java, the prototype pattern is recommended to be implemented as follows. First, create an interface with a method for cloning objects. In this example, `Prototype` interface accomplishes this with its `copy` method. ```java public abstract class Prototype implements Cloneable { @@ -50,17 +44,13 @@ public abstract class Prototype implements Cloneable { } ``` -Our example contains a hierarchy of different creatures. For example, let's look at `Beast` and -`OrcBeast` classes. +Our example contains a hierarchy of different creatures. For example, let's look at `Beast` and `OrcBeast` classes. ```java @EqualsAndHashCode(callSuper = false) @NoArgsConstructor public abstract class Beast extends Prototype { - - public Beast(Beast source) { - } - + public Beast(Beast source) {} } @EqualsAndHashCode(callSuper = false) @@ -78,19 +68,15 @@ public class OrcBeast extends Beast { public String toString() { return "Orcish wolf attacks with " + weapon; } - } ``` -We don't want to go into too many details, but the full example contains also base classes `Mage` -and `Warlord` and there are specialized implementations for those for elves in addition to orcs. +We don't want to go into too many details, but the full example contains also base classes `Mage` and `Warlord` and there are specialized implementations for those for elves in addition to orcs. -To take full advantage of the prototype pattern, we create `HeroFactory` and `HeroFactoryImpl` -classes to produce different kinds of creatures from prototypes. +To take full advantage of the prototype pattern, we create `HeroFactory` and `HeroFactoryImpl` classes to produce different kinds of creatures from prototypes. ```java public interface HeroFactory { - Mage createMage(); Warlord createWarlord(); Beast createBeast(); @@ -117,8 +103,7 @@ public class HeroFactoryImpl implements HeroFactory { } ``` -Now, we are able to show the full prototype pattern in action producing new creatures by cloning -existing instances. +Now, we are able to show the full prototype pattern in action producing new creatures by cloning existing instances. ```java var factory = new HeroFactoryImpl( @@ -163,21 +148,40 @@ Orcish wolf attacks with laser ## Applicability -Use the Prototype pattern when a system should be independent of how its products are created, -composed, represented and - * When the classes to instantiate are specified at run-time, for example, by dynamic loading. * To avoid building a class hierarchy of factories that parallels the class hierarchy of products. -* When instances of a class can have one of only a few different combinations of state. It may be -more convenient to install a corresponding number of prototypes and clone them rather than -instantiating the class manually, each time with the appropriate state. +* When instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state. * When object creation is expensive compared to cloning. +* When the concrete classes to instantiate are unknown until runtime. ## Known uses -* [java.lang.Object#clone()](http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29) +* In Java, the `Object.clone()` method is a classic implementation of the Prototype pattern. +* GUI libraries often use prototypes for creating buttons, windows, and other widgets. +* In game development, creating multiple objects (like enemy characters) with similar attributes. + +## Consequences + +Benefits: + +* Hides the complexities of instantiating new objects. +* Reduces the number of classes. +* Allows adding and removing objects at runtime. + +Trade-offs: + +* Requires implementing a cloning mechanism which might be complex. +* Deep cloning can be difficult to implement correctly, especially if the classes have complex object graphs with circular references. + +## Related patterns + +- [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Both involve creating objects, but Prototype uses cloning of a prototype instance whereas Abstract Factory creates objects using factory methods. +- [Singleton](https://java-design-patterns.com/patterns/singleton/): Singleton can use a prototype for creating instances if it allows cloning of its single instance. +- [Composite](https://java-design-patterns.com/patterns/composite/): Prototypes are often used within composites to allow for dynamic creation of component trees. ## Credits * [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) +* [Effective Java](https://amzn.to/4cGk2Jz) * [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b) +* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)