🧩 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
ExporterPrototype
in 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(): ExporterPrototype
for creating a copy - Declares
export(data: string): void
for output functionality
-
PdfExporter
- A concrete prototype class
- Implements
clone
to return a copy of itself - Implements
export
to output data in PDF format - Provides an
enableLogging
method 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
clone
method
This design is highly effective when new objects need to be based on existing ones,
improving both flexibility and reusability of the codebase.