zoukankan      html  css  js  c++  java
  • [Python设计模式] 第9章 如何准备多份简历——原型模式

    github地址:https://github.com/cheesezh/python_design_patterns

    题目

    设计一个简历类,必须有姓名,可以设置性别和年龄,即个人信息,可以设置曾就职公司和工作时间,即工作经历。

    基础版本

    class Resume():
        
        def __init__(self, name):
            self.name = name  # python默认成员变量公开
            self.__sex = None  # python默认成员变量公开,加__表示私有
            self.__age = None  # python默认成员变量公开,加__表示私有
            self.__time_area = None  # python默认成员变量公开,加__表示私有
            self.__company = None  # python默认成员变量公开,加__表示私有
            
        def set_personal_info(self, sex, age):
            self.__sex = sex
            self.__age = age
        
        def set_work_experience(self, time_area, company):
            self.__time_area = time_area
            self.__company = company
            
        def display(self):
            print("{}	{}	{}".format(self.name, self.__sex, self.__age))
            print("{}	{}".format(self.__time_area, self.__company))
        
    def main():
        resume_a = Resume("鸣人")
        resume_a.set_personal_info("男", "29")
        resume_a.set_work_experience("2016-2018", "木叶公司")
        
        resume_b = Resume("鸣人")
        resume_b.set_personal_info("男", "29")
        resume_b.set_work_experience("2016-2018", "木叶公司")
        
        resume_c = Resume("鸣人")
        resume_c.set_personal_info("男", "29")
        resume_c.set_work_experience("2016-2018", "木叶公司")
        
        resume_a.display()
        resume_b.display()
        resume_c.display()
        
    main()
    
    鸣人	男	29
    2016-2018	木叶公司
    鸣人	男	29
    2016-2018	木叶公司
    鸣人	男	29
    2016-2018	木叶公司
    

    点评

    • 上述main函数中生成简历的方法,相当于手写简历,三份简历要三次实例化
    • 而且如果要更改某个字段,比如把时间从2016-2018改成2017-2018,那么同样修改三次

    那如果这样写呢?

    def main():
        resume_a = Resume("鸣人")
        resume_a.set_personal_info("男", "29")
        resume_a.set_work_experience("2016-2018", "木叶公司")
        
        resume_b = resume_a
        
        resume_c = resume_a
        
        resume_a.display()
        resume_b.display()
        resume_c.display()
        
    main()
    
    鸣人	男	29
    2016-2018	木叶公司
    鸣人	男	29
    2016-2018	木叶公司
    鸣人	男	29
    2016-2018	木叶公司
    

    点评

    • 这里传递的是引用,而不是具体的值,相当于在简历b和简历c上没有实际内容,而是写着“详见简历a”
    • 可以使用clone的方法解决这个问题,即原型模式

    原型模式

    原型模式,即用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象[DP]。也就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。

    from abc import ABCMeta, abstractmethod
    from copy import copy
    
    class Prototype():
        """
        抽象原型类
        """
        __metaclass__ = ABCMeta
        def __init__(self, id):
            self.id = id
            
        @abstractmethod
        def clone(self):
            pass
    
    class ConcretePrototypeOne(Prototype):
        """
        具体原型类
        """
        def __init__(self, id):
            super().__init__(id)
        
        def clone(self):
            return copy(self)  # 1. 浅拷贝copy.copy() 或 深拷贝copy.deepcopy() 2. Python无需强制类型转换
    
    def main():
        prototype1 = ConcretePrototypeOne("1")
        prototype1_cloned = prototype1.clone()  
        print(prototype1_cloned.id)
        
    main()
    
    1
    

    Python中的浅拷贝与深拷贝

    Python中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的copy模块。

    • copy.copy(浅拷贝):只拷贝顶层对象,不会拷贝顶层对象的内部的对象成员变量;
    • copy.deepcopy(深拷贝):拷贝对象及其子对象

    按照基础版本的简历类定义,成员变量的类型都是基本数据类型(string),所以使用浅拷贝即可。那么什么时候用深拷贝呢?假如我们将工作经历定义为一个单独的类WorkExperience,那么简历类中就会有一个成员变量的类型是WorkExperience,如果这时候需要拷贝操作,就需要用深拷贝了。

    深拷贝原型模式

    from copy import deepcopy
    
    
    class WorkExperience():
    
        def __init__(self, time_area="", company=""):
            self.time_area = time_area
            self.company = company
            
    class Resume():
        
        def __init__(self, name):
            self.name = name  # python默认成员变量公开
            self.__sex = None  # python默认成员变量公开,加__表示私有
            self.__age = None  # python默认成员变量公开,加__表示私有
            self.__work_expereince = WorkExperience()  # python默认成员变量公开,加__表示私有
            
        def set_personal_info(self, sex, age):
            self.__sex = sex
            self.__age = age
        
        def set_work_experience(self, time_area, company):
            self.__work_expereince.time_area = time_area
            self.__work_expereince.company = company
            
        def display(self):
            print("{}	{}	{}".format(self.name, self.__sex, self.__age))
            print("{}	{}".format(self.__work_expereince.time_area, self.__work_expereince.company))
            
        def deep_clone(self):
            """
            深拷贝方法
            """
            return deepcopy(self)
        
        def clone(self):
            """
            浅拷贝方法
            """
            return copy(self)
        
    
    def main():
        resume_a = Resume("鸣人")
        resume_a.set_personal_info("男", "29")
        resume_a.set_work_experience("2016-2018", "木叶公司")
        
        resume_b = resume_a.clone()
        resume_b.set_work_experience("2018-2019", "王者学校")
        
        resume_c = resume_a.clone()
        resume_c.set_personal_info("男", "24")
        resume_c.set_work_experience("2019-2020", "问问公司")
        
        resume_a.display()
        resume_b.display()
        resume_c.display()
        
    def deep_main():
        resume_a = Resume("鸣人")
        resume_a.set_personal_info("男", "29")
        resume_a.set_work_experience("2016-2018", "木叶公司")
        
        resume_b = resume_a.deep_clone()
        resume_b.set_work_experience("2018-2019", "王者学校")
        
        resume_c = resume_a.deep_clone()
        resume_c.set_personal_info("男", "24")
        resume_c.set_work_experience("2019-2020", "问问公司")
        
        resume_a.display()
        resume_b.display()
        resume_c.display()
    
    print("---浅拷贝, 工作经历都被修改成最后一次的值---")
    main()
    print("--------深拷贝, 工作经历为不同的值--------")
    deep_main()
    
    ---浅拷贝, 工作经历都被修改成最后一次的值---
    鸣人	男	29
    2019-2020	问问公司
    鸣人	男	29
    2019-2020	问问公司
    鸣人	男	24
    2019-2020	问问公司
    --------深拷贝, 工作经历为不同的值--------
    鸣人	男	29
    2016-2018	木叶公司
    鸣人	男	29
    2018-2019	王者学校
    鸣人	男	24
    2019-2020	问问公司
  • 相关阅读:
    find命令之xargs
    find命令之exec
    find 命令概览
    mv命令
    locate 命令
    whereis 命令
    linux which 查看可执行文件的位置
    Linux应用总结:自动删除n天前日志
    Visual Studio
    Visual Studio- “无法启动此程序,因为计算机中丢失 xxx.dll尝试重新安装该程序以解决此问题"
  • 原文地址:https://www.cnblogs.com/CheeseZH/p/9398461.html
Copyright © 2011-2022 走看看