Summer SALE
原型

Python 原型模式讲解和代码示例

原型是一种创建型设计模式 使你能够复制对象 甚至是复杂对象 而又无需使代码依赖它们所属的类

所有的原型类都必须有一个通用的接口 使得即使在对象所属的具体类未知的情况下也能复制对象 原型对象可以生成自身的完整副本 因为相同类的对象可以相互访问对方的私有成员变量

复杂度

流行度

使用示例 Python 的 Cloneable  克隆 组件就是立即可用的原型模式

识别方法 原型可以简单地通过 clone copy等方法来识别

概念示例

本例说明了原型设计模式的结构并重点回答了下面的问题

  • 它由哪些类组成
  • 这些类扮演了哪些角色
  • 模式中的各个元素会以何种方式相互关联

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 repeatedly. 

原型在其他编程语言中的实现

C# 原型模式讲解和代码示例 C++ 原型模式讲解和代码示例 Go 原型模式讲解和代码示例 Java 原型模式讲解和代码示例 PHP 原型模式讲解和代码示例 Ruby 原型模式讲解和代码示例 Rust 原型模式讲解和代码示例 Swift 原型模式讲解和代码示例 TypeScript 原型模式讲解和代码示例