To create a "Perfect" Prototype class that embodies the Prototype Pattern effectively, we need a flexible and reusable solution. Here's a step-by-step implementation:
Key Features:
- Flexible Initialization: Accepts any keyword arguments to set attributes.
- Cloning Mechanism: Supports both shallow and deep cloning.
- State Management: Tracks original and modified states for consistency.
- Type Safety: Clones preserve the exact class type.
- Dynamic Attribute Handling: Allows runtime attribute changes.
Solution Code:
import copy
class Prototype:
def __init__(self, **kwargs):
"""Initialize with arbitrary attributes."""
self._original_state = kwargs.copy()
self._current_state = kwargs.copy()
for key, value in kwargs.items():
setattr(self, key, value)
def clone(self, deep=False):
"""Create a clone of the prototype (shallow by default)."""
new_instance = object.__new__(self.__class__)
new_instance._original_state = self._original_state.copy()
new_instance._current_state = self._current_state.copy()
if deep:
# Deep copy all attributes
for key in self._current_state:
setattr(new_instance, key, copy.deepcopy(getattr(self, key)))
else:
# Shallow copy attributes
for key in self._current_state:
setattr(new_instance, key, getattr(self, key))
return new_instance
def reset(self):
"""Reset to original state."""
self._current_state = self._original_state.copy()
for key in self._original_state:
setattr(self, key, self._original_state[key])
def __repr__(self):
return f"{self.__class__.__name__}({self._current_state})"
Explanation:
-
Initialization (
__init__):- Stores initial attributes in
_original_stateand_current_state. - Dynamically sets attributes via
setattr.
- Stores initial attributes in
-
Cloning (
clone):- Shallow Clone (Default): Copies attribute references (efficient, but shared mutable objects).
- Deep Clone: Recursively copies all attributes (independent state, safe for mutable objects).
- Uses
object.__new__to create an instance without calling__init__, preserving class type.
-
State Management (
reset):- Reverts attributes to their original values using
_original_state.
- Reverts attributes to their original values using
-
Representation (
__repr__):Provides a clear string representation of the current state.
Usage Example:
print(prototype) # Prototype({'name': 'Original', 'data': [1, 2, 3]})
# Shallow clone (shares mutable objects)
shallow_clone = prototype.clone()
shallow_clone.data.append(4)
print(prototype.data) # [1, 2, 3, 4] (shared reference)
# Deep clone (independent state)
deep_clone = prototype.clone(deep=True)
deep_clone.data.append(5)
print(prototype.data) # [1, 2, 3, 4] (unaffected)
# Reset prototype
prototype.reset()
print(prototype) # Prototype({'name': 'Original', 'data': [1, 2, 3]})
Why This is "Perfect":
- Flexibility: Handles any attributes and cloning type.
- Safety: Prevents unintended side effects with deep cloning.
- Consistency: Maintains original state for resets.
- Type Preservation: Clones are instances of the exact class.
- Clarity: Clear state tracking and representation.
This implementation provides a robust foundation for the Prototype Pattern, suitable for scenarios requiring object duplication with controlled state sharing.
Request an On-site Audit / Inquiry