From c43d39f6df8bc970f0270b867b3808ce9d14a3f5 Mon Sep 17 00:00:00 2001 From: theartcher Date: Tue, 28 Oct 2025 17:17:32 +0100 Subject: [PATCH 1/2] W.I.P, started on page content --- docs/Creational/prototype.mdx | 105 +++++++++++++++++++++- src/components/HomepageFeatures/index.tsx | 28 +++--- 2 files changed, 119 insertions(+), 14 deletions(-) diff --git a/docs/Creational/prototype.mdx b/docs/Creational/prototype.mdx index e92d833..8e9998d 100644 --- a/docs/Creational/prototype.mdx +++ b/docs/Creational/prototype.mdx @@ -1,5 +1,108 @@ --- title: Prototype +hide_title: true --- -This is Prototype Pattern page +import { CreationalPatternTag } from "@site/src/components/pattern-page-features/pattern-alias-and-tag"; +import TwoColumnProsCons from "@site/src/components/pattern-page-features/pros-and-cons"; +import TOCInline from '@theme/TOCInline'; +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; +import Applicability from "@site/src/components/pattern-page-features/applicability"; + + +--- + +**Prototype** is a pattern that lets you copy existing objects without making your code dependant on their actual implementations or classes. + +## 🧩The problem + +Let's say you want to create a copy or clone of an existing object. However, the exact details of the object's class or structure aren't fully known at runtime, or the object is part of a complex hierarchy. You want to avoid tight coupling between your code and the specific classes of the objects you're working with. Additionally, creating new instances of these objects through traditional means (like using constructors) might be inefficient or impractical, especially if the objects are complex or resource-intensive to create from scratch. Furthermore, there are times when you cannot create an object directly because the class of the object is hidden, or you want to avoid the overhead of creating a new instance from scratch. + +## 🛠️Solutions + +The Prototype pattern addresses these challenges by allowing you to create new objects by cloning existing ones, known as **prototypes**. Instead of initializing objects directly, you copy an existing object, which serves as a prototype. This is typically achieved through a method like `clone()`, which creates a copy of the object. An object which supports cloning or copying is referred to as a *prototype*. When you have lots of configurations or dozens of fields, prototyping may serve as a good alternative to subclassing. + + +### 🏛️Metaphors + +Imagine a sculptor who has created a beautiful statue. Instead of sculpting a new statue from scratch each time, the sculptor makes a mold of the original statue. Whenever a new statue is needed, the sculptor simply pours material into the mold to create an exact replica. In this scenario, the original statue is the prototype, and the mold allows for easy duplication without needing to recreate the entire sculpture process. + +### 💡Real-world examples +Common practical scenarios for applying the Prototype pattern include: + +- Cloning complex objects in a game (e.g., characters, items) without knowing their exact class. +- Creating a new document in a word processor by copying an existing one, preserving its formatting and content. +- [Mitotic cell division](https://en.wikipedia.org/wiki/Mitosis) in biology, where a cell replicates its DNA and divides to form two identical daughter cells. + +## ⚖️ Pros and Cons + + + + +## 🔍Applicability + + + + +## 🧭Implementation Plan + +To implement a Prototype manually: + +1. Create a Prototype interface with a clone method, or alternatively add a `clone()` method to the existing classes. +2. Implement the Prototype interface in the classes you want to clone. +3. Use the clone method to create copies of objects instead of using constructors. + + +### 💻Code samples + + + + +```ts +//ts code here +``` + + + + +```python +#python code here +``` + + + +### 🎮Playground + +:::note + +This sample is to get a 'feel' for the pattern. The code itself may not reflect a correct implementation of the pattern. + +::: + +```jsx live +// code +``` + +## 🔗Relations to other patterns +- x +--- + +## 📚Sources +Information used in this page was collected from various reliable sources: + +- [Refactoring Guru - Protoype](https://refactoring.guru/design-patterns/prototype) +- [Geeks for Geeks - Prototype Design Pattern](https://www.geeksforgeeks.org/system-design/prototype-design-pattern/) +- [Wikipedia - Prototype Pattern](https://en.wikipedia.org/wiki/Prototype_pattern) \ No newline at end of file diff --git a/src/components/HomepageFeatures/index.tsx b/src/components/HomepageFeatures/index.tsx index c2551fb..7c5c7cb 100644 --- a/src/components/HomepageFeatures/index.tsx +++ b/src/components/HomepageFeatures/index.tsx @@ -1,18 +1,20 @@ -import type {ReactNode} from 'react'; -import clsx from 'clsx'; -import Heading from '@theme/Heading'; -import styles from './styles.module.css'; +import type { ReactNode } from "react"; +import clsx from "clsx"; +import Heading from "@theme/Heading"; +import styles from "./styles.module.css"; + +// FUTURE_WORK https://github.com/S7-OpenLearning-Individual/DesignPatternPedia/issues/5: Improve home page. type FeatureItem = { title: string; - Svg: React.ComponentType>; + Svg: React.ComponentType>; description: ReactNode; }; const FeatureList: FeatureItem[] = [ { - title: 'Easy to Use', - Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, + title: "Easy to Use", + Svg: require("@site/static/img/undraw_docusaurus_mountain.svg").default, description: ( <> Docusaurus was designed from the ground up to be easily installed and @@ -21,8 +23,8 @@ const FeatureList: FeatureItem[] = [ ), }, { - title: 'Focus on What Matters', - Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, + title: "Focus on What Matters", + Svg: require("@site/static/img/undraw_docusaurus_tree.svg").default, description: ( <> Docusaurus lets you focus on your docs, and we'll do the chores. Go @@ -31,8 +33,8 @@ const FeatureList: FeatureItem[] = [ ), }, { - title: 'Powered by React', - Svg: require('@site/static/img/undraw_docusaurus_react.svg').default, + title: "Powered by React", + Svg: require("@site/static/img/undraw_docusaurus_react.svg").default, description: ( <> Extend or customize your website layout by reusing React. Docusaurus can @@ -42,9 +44,9 @@ const FeatureList: FeatureItem[] = [ }, ]; -function Feature({title, Svg, description}: FeatureItem) { +function Feature({ title, Svg, description }: FeatureItem) { return ( -
+
From 8575d29308a32fb7cb8e1cf8ccdd97df1d7fbb4c Mon Sep 17 00:00:00 2001 From: theartcher Date: Wed, 29 Oct 2025 11:37:28 +0100 Subject: [PATCH 2/2] Finish page --- docs/Creational/prototype.mdx | 115 ++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 5 deletions(-) diff --git a/docs/Creational/prototype.mdx b/docs/Creational/prototype.mdx index 8e9998d..72e9f33 100644 --- a/docs/Creational/prototype.mdx +++ b/docs/Creational/prototype.mdx @@ -64,6 +64,8 @@ To implement a Prototype manually: 1. Create a Prototype interface with a clone method, or alternatively add a `clone()` method to the existing classes. 2. Implement the Prototype interface in the classes you want to clone. 3. Use the clone method to create copies of objects instead of using constructors. +4. [OPTIONAL] Create a Prototype Registry, a centralized place to store and manage prototype instances, or use a Factory that utilizes prototypes for object creation. +5. Replace the direct call to the constructor with calls to the clone method. ### 💻Code samples @@ -72,14 +74,53 @@ To implement a Prototype manually: ```ts -//ts code here +// Prototype interface +interface Prototype { + clone(): Prototype; +} + +// Concrete prototype +class Person implements Prototype { + name: string; + age: number; + + constructor(name: string, age: number) { + this.name = name; + this.age = age; + } + + clone(): Prototype { + return new Person(this.name, this.age); + } +} + +// Usage +const original = new Person("Alice", 30); +const copy = original.clone(); +console.log(copy); // Person { name: 'Alice', age: 30 } + ``` ```python -#python code here +import copy # https://docs.python.org/3/library/copy.html + +# Python does not support interfaces natively, so we can just define a clone method in the class. +class Person: + def __init__(self, name, age): + self.name = name + self.age = age + + def clone(self): + return copy.deepcopy(self) + +# Usage +original = Person("Alice", 30) +copy_person = original.clone() +print(copy_person.name, copy_person.age) # Alice 30 + ``` @@ -93,16 +134,80 @@ This sample is to get a 'feel' for the pattern. The code itself may not reflect ::: ```jsx live -// code +function PrototypeDemo() { + // The prototype object with shared methods + const animalPrototype = { + speak() { + return `Hi, I'm a ${this.type} called ${this.name}`; + } + }; + + // Function to clone the prototype and create a new animal + function createAnimal(type, name) { + const animal = Object.create(animalPrototype); + animal.type = type; + animal.name = name; + return animal; + } + + const [type, setType] = React.useState("Cat"); + const [name, setName] = React.useState("Whiskers"); + const [animals, setAnimals] = React.useState([]); + + // Add a new animal to the list + function handleCreate() { + const animal = createAnimal(type, name); + setAnimals([animal, ...animals]); + } + + return ( +
+

Prototype Pattern — Playground

+
+ + + +
+
    + {animals.map((animal, i) => ( +
  • {animal.speak()}
  • + ))} +
+
+ Each new animal is cloned from animalPrototype. Try changing the + fields and creating multiple animals to see prototype sharing in action! +
+
+ ); +} + ``` ## 🔗Relations to other patterns -- x +- Designs that make heavy use of [Composite](/docs/Structural/composite.mdx) and [Decorator](/docs/Structural/decorator.mdx) can often benefit from using [Prototype](/docs/Creational/prototype). Applying the pattern lets you clone complex structures instead of re-constructing them from scratch. +- [Prototypes](/docs/Creational/prototype) can help when you need to save copies of [Commands](/docs/Behavioural/command.mdx) into history. +- [Abstract Factories](/docs/Creational/abstract-factory) classes are often based on a set of [Factory Methods](/docs/Creational/factory-method.mdx), but you can also use [Prototype](/docs/Creational/prototype) to compose the methods on these classes. +- [Abstract Factories](/docs/Creational/abstract-factory), [Builders](/docs/Creational/builder), and [Prototypes](/docs/Creational/prototype) can be implemented as [Singleton](/docs/Creational/singleton). + --- ## 📚Sources Information used in this page was collected from various reliable sources: -- [Refactoring Guru - Protoype](https://refactoring.guru/design-patterns/prototype) +- [Refactoring Guru - Prototype](https://refactoring.guru/design-patterns/prototype) - [Geeks for Geeks - Prototype Design Pattern](https://www.geeksforgeeks.org/system-design/prototype-design-pattern/) - [Wikipedia - Prototype Pattern](https://en.wikipedia.org/wiki/Prototype_pattern) \ No newline at end of file