# 原型

原型模式的使用场景

大体上有两种使用场景

1.在需要一个类的大量对象的时候，使用原型模式是最佳选择，因为原型模式是在内存中对这个对象进行拷贝，要比直接new这个对象性能要好很多，在这种情况下，需要的对象越多，原型模式体现出的优点越明显。

2.如果一个对象的初始化需要很多其他对象的数据准备或其他资源的繁琐计算，那么可以使用原型模式。

3.当需要一个对象的大量公共信息，少量字段进行个性化设置的时候，也可以使用原型模式拷贝出现有对象的副本进行加工处理。

```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/10/7 10:17 PM
# @Author  : xinfa.jiang
# @Site    : 
# @File    : prototype.py
# @Software: PyCharm

"""
原型模式
用原型实例指定创建对象的种类, 并且通过拷贝这些原型创建新的对象
- 原型模型其实是从一个对象再创建另外一个可定制的对象, 而且不需要知道任何创建细节
- 一般在初始化信息不发生变化的情况下, 克隆是最好的办法, 既隐藏了对象创建的细节, 有提高了性能
在不指定类名的前提下生成实例
- 对象种类繁多, 无法将它们整合到一个类中
- 难以根据类生成实例时
- 解耦框架与生成实例: 让框架不依赖于具体的类, 不能指定类名来生成实例, 要实现注册一个原型
  然后, 通过复制该实例来生成新的实例
why: 一旦在代码中出现要使用的类的名字, 就无法与该类分离开来, 也就无法实现复用
示例:
"""
import copy
from abc import ABCMeta, abstractmethod


class Prototype(object):
    """
    原型类, 声明一个克隆自身的接口
    """
    __metaclass__ = ABCMeta

    def __init__(self, id):
        self.__id = id

    @property
    def id(self):
        return self.__id

    @id.setter
    def id(self, value):
        self.__id = value

    @abstractmethod
    def clone(self):
        pass


class ConcretePrototypeA(Prototype):
    """
    具体原型类, 实现一个克隆自身的操作
    """

    def clone(self):
        # 浅拷贝, 注意
        return copy.copy(self)


class ConcretePrototypeB(Prototype):
    """
    具体原型类, 实现一个克隆自身的操作
    """

    def clone(self):
        return copy.copy(self)


class Manager(object):
    def __init__(self):
        self._dict = {}

    def register(self, name, prototype):
        self._dict[name] = prototype

    def create(self, proto_name):
        p = self._dict.get(proto_name)
        return p.clone()


if __name__ == '__main__':
    ca = ConcretePrototypeA(1)
    c2 = ca.clone()
    print(c2.id)

    # with manager
    cb = ConcretePrototypeB(2)

    m = Manager()
    m.register("ca", ca)
    m.register("cb", cb)

    x = m.create("cb")
    print(x.id)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://im-qianuxn.gitbook.io/pytorch/ji-suan-ji/pattern/prototype.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
