🧩 Prototype Pattern
✅ Intent​
- Reuse pre-initialized logic and structure by duplicating a prototype instance
- Clone a base object using
clone()and apply modifications only where needed
✅ Motivation​
- When you have logic or structures that are "almost the same", cloning a template improves maintainability and reusability
- Ideal when many similar instances are created from scratch using
new, and you want to centralize shared setup
✅ When to Use​
- When the initial state is mostly shared, and only a few properties differ
- Useful for duplicating forms, configuration objects, notification templates, UI layouts, etc.
✅ Code Example​
- TypeScript
- PHP
- Python
interface ExporterPrototype {
clone(): ExporterPrototype;
export(data: string): void;
}
class PdfExporter implements ExporterPrototype {
constructor(private withLog: boolean = false) {}
clone(): ExporterPrototype {
return new PdfExporter(this.withLog);
}
export(data: string): void {
if (this.withLog) console.log("é–‹å§‹ãƒã‚°");
console.log(`PDF出力: ${data}`);
if (this.withLog) console.log("完了ãƒã‚°");
}
enableLogging(): void {
this.withLog = true;
}
}
// 利用例
const baseExporter = new PdfExporter();
baseExporter.enableLogging();
const cloned = baseExporter.clone();
cloned.export("請求書");
<?php
interface ExporterPrototype {
public function clone(): ExporterPrototype;
public function export(string $data): void;
}
class PdfExporter implements ExporterPrototype {
public function __construct(private bool $withLog = false) {}
public function clone(): ExporterPrototype {
return new PdfExporter($this->withLog);
}
public function export(string $data): void {
if ($this->withLog) echo "é–‹å§‹ãƒã‚°\n";
echo "PDF出力: {$data}\n";
if ($this->withLog) echo "完了ãƒã‚°\n";
}
public function enableLogging(): void {
$this->withLog = true;
}
}
// 利用例
$baseExporter = new PdfExporter();
$baseExporter->enableLogging();
$cloned = $baseExporter->clone();
$cloned->export("請求書");
import copy
from abc import ABC, abstractmethod
class ExporterPrototype(ABC):
@abstractmethod
def clone(self): pass
@abstractmethod
def export(self, data: str): pass
class PdfExporter(ExporterPrototype):
def __init__(self, with_log: bool = False):
self.with_log = with_log
def clone(self) -> "PdfExporter":
return copy.deepcopy(self)
def enable_logging(self):
self.with_log = True
def export(self, data: str):
if self.with_log:
print("é–‹å§‹ãƒã‚°")
print(f"PDF出力: {data}")
if self.with_log:
print("完了ãƒã‚°")
# 利用例
base_exporter = PdfExporter()
base_exporter.enable_logging()
cloned = base_exporter.clone()
cloned.export("請求書")
✅ Explanation​
This code applies the Prototype pattern to clone an existing object
and generate a new instance with the same properties.
The Prototype pattern creates new objects by copying an existing instance,
instead of instantiating a new one from its class directly.
1. Overview of the Prototype Pattern​
-
Prototype: Interface that provides a cloning method
- Represented by
ExporterPrototypein this code
- Represented by
-
ConcretePrototype: Implements the prototype interface and provides cloning logic
- Represented by
PdfExporter
- Represented by
-
Client: Uses a prototype object and clones it to create new instances
- Represented by the call to
baseExporter.clone()
- Represented by the call to
2. Key Classes and Their Roles​
-
ExporterPrototype- Common interface for prototypes
- Declares
clone(): ExporterPrototypefor creating a copy - Declares
export(data: string): voidfor output functionality
-
PdfExporter- A concrete prototype class
- Implements
cloneto return a copy of itself - Implements
exportto output data in PDF format - Provides an
enableLoggingmethod to customize cloned instances
3. UML Class Diagram​
4. Benefits of the Prototype Pattern​
- Flexible Object Creation: Create new instances based on existing objects without relying on constructors
- Avoids Repetitive Initialization: Use clones to avoid repeating complex setup logic
- Extensibility: Adding a new class only requires implementing the
clonemethod
This design is highly effective when new objects need to be based on existing ones,
improving both flexibility and reusability of the codebase.