使用示例:Python 的 Cloneable
(克隆) 组件就是立即可用的原型模式。
识别方法:原型可以简单地通过 clone
或 copy
等方法来识别。
01概念示例
本例说明了原型设计模式的结构并重点回答了下面的问题:
- 它由哪些类组成?
- 这些类扮演了哪些角色?
- 模式中的各个元素会以何种方式相互关联?
main.py: 概念示例
import copy class SelfReferencingEntity: def __init__(self): self.parent = None def set_parent(self, parent): self.parent = parent class SomeComponent: """ Python provides its own interface of Prototype via `copy.copy` and `copy.deepcopy` functions. And any class that wants to implement custom implementations have to override `__copy__` and `__deepcopy__` member functions. """ def __init__(self, some_int, some_list_of_objects, some_circular_ref): self.some_int = some_int self.some_list_of_objects = some_list_of_objects self.some_circular_ref = some_circular_ref def __copy__(self): """ Create a shallow copy. This method will be called whenever someone calls `copy.copy` with this object and the returned value is returned as the new shallow copy. """ #First, let's create copies of the nested objects. some_list_of_objects = copy.copy(self.some_list_of_objects) some_circular_ref = copy.copy(self.some_circular_ref) #Then, let's clone the object itself, using the prepared clones of the #nested objects. new = self.__class__( self.some_int, some_list_of_objects, some_circular_ref ) new.__dict__.update(self.__dict__) return new def __deepcopy__(self, memo=None): """ Create a deep copy. This method will be called whenever someone calls `copy.deepcopy` with this object and the returned value is returned as the new deep copy. What is the use of the argument `memo`? Memo is the dictionary that is used by the `deepcopy` library to prevent infinite recursive copies in instances of circular references. Pass it to all the `deepcopy` calls you make in the `__deepcopy__` implementation to prevent infinite recursions. """ if memo is None: memo = {} #First, let's create copies of the nested objects. some_list_of_objects = copy.deepcopy(self.some_list_of_objects, memo) some_circular_ref = copy.deepcopy(self.some_circular_ref, memo) #Then, let's clone the object itself, using the prepared clones of the #nested objects. new = self.__class__( self.some_int, some_list_of_objects, some_circular_ref ) new.__dict__ = copy.deepcopy(self.__dict__, memo) return new if __name__ == "__main__": list_of_objects = [1, {1, 2, 3}, [1, 2, 3]] circular_ref = SelfReferencingEntity() component = SomeComponent(23, list_of_objects, circular_ref) circular_ref.set_parent(component) shallow_copied_component = copy.copy(component) #Let's change the list in shallow_copied_component and see if it changes in #component. shallow_copied_component.some_list_of_objects.append("another object") if component.some_list_of_objects[-1] == "another object": print( "Adding elements to `shallow_copied_component`'s " "some_list_of_objects adds it to `component`'s " "some_list_of_objects." ) else: print( "Adding elements to `shallow_copied_component`'s " "some_list_of_objects doesn't add it to `component`'s " "some_list_of_objects." ) #Let's change the set in the list of objects. component.some_list_of_objects[1].add(4) if 4 in shallow_copied_component.some_list_of_objects[1]: print( "Changing objects in the `component`'s some_list_of_objects " "changes that object in `shallow_copied_component`'s " "some_list_of_objects." ) else: print( "Changing objects in the `component`'s some_list_of_objects " "doesn't change that object in `shallow_copied_component`'s " "some_list_of_objects." ) deep_copied_component = copy.deepcopy(component) #Let's change the list in deep_copied_component and see if it changes in #component. deep_copied_component.some_list_of_objects.append("one more object") if component.some_list_of_objects[-1] == "one more object": print( "Adding elements to `deep_copied_component`'s " "some_list_of_objects adds it to `component`'s " "some_list_of_objects." ) else: print( "Adding elements to `deep_copied_component`'s " "some_list_of_objects doesn't add it to `component`'s " "some_list_of_objects." ) #Let's change the set in the list of objects. component.some_list_of_objects[1].add(10) if 10 in deep_copied_component.some_list_of_objects[1]: print( "Changing objects in the `component`'s some_list_of_objects " "changes that object in `deep_copied_component`'s " "some_list_of_objects." ) else: print( "Changing objects in the `component`'s some_list_of_objects " "doesn't change that object in `deep_copied_component`'s " "some_list_of_objects." ) print( f"id(deep_copied_component.some_circular_ref.parent): " f"{id(deep_copied_component.some_circular_ref.parent)}" ) print( f"id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent): " f"{id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent)}" ) print( "^^ This shows that deepcopied objects contain same reference, they " "are not cloned repeatedly." )
Output.txt: 执行结果
Adding elements to `shallow_copied_component`'s some_list_of_objects adds it to `component`'s some_list_of_objects. Changing objects in the `component`'s some_list_of_objects changes that object in `shallow_copied_component`'s some_list_of_objects. Adding elements to `deep_copied_component`'s some_list_of_objects doesn't add it to `component`'s some_list_of_objects. Changing objects in the `component`'s some_list_of_objects doesn't change that object in `deep_copied_component`'s some_list_of_objects. id(deep_copied_component.some_circular_ref.parent): 4429472784 id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent): 4429472784 ^^ This shows that deepcopied objects contain same reference, they are not cloned