zoukankan      html  css  js  c++  java
  • 设计模式之原型模式

    设计模式之原型模式

    Intro 简介

    原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

    原型模式其实就是从一个对象再创建另外一个可定制的对象而且不需要知道任何创建的细节。

    实现方式

    实现方式大致如下:

    在 c# 中可以借助 ICloneable 接口和 MemberwiseClone 方法来方便的实现原型模式,需要注意的是这个方法是浅复制,当对象内嵌套了另外一个对象的时候,尤其需要注意。

    // 浅复制
    public object Clone() => MemberwiseClone();
    

    示例

    简单的简历,所有的字段属性都是简单类型

    public class SimpleResume : ICloneable
    {
        private string _name;
        private string _email;
    
        private string _timePeriod;
        private string _company;
    
        public void SetPersonalInfo(string name, string email)
        {
            _name = name;
            _email = email;
        }
    
        public void SetWorkExperience(string company, string timePeriod)
        {
            _company = company;
            _timePeriod = timePeriod;
        }
    
        public void Display()
        {
            Console.WriteLine($"{_name} {_email}");
            Console.WriteLine($"工作经历:{_timePeriod} {_company}");
        }
    
        public object Clone() => MemberwiseClone();
    }
    
    var resume = new SimpleResume();
    resume.SetPersonalInfo("小明", "xiaoming@abc.xyz");
    resume.SetWorkExperience("xxx公司", "1990~2000");
    resume.Display();
    var resume1 = (SimpleResume)resume.Clone();
    resume1.SetWorkExperience("xxx企业", "1998~1999");
    resume1.Display();
    var resume2 = (SimpleResume)resume.Clone();
    resume2.SetPersonalInfo("xiaohong", "xiaohong@abc.xyz");
    resume2.Display();
    

    深复制示例,下面是一个复杂一些的简历,里面包含了一个 WorkExperience 是另外一个类型,直接浅复制的话_workExperience 仍然指向原来的引用,来看下面的示例是怎么解决这个问题的

    public class WorkExperience : ICloneable
    {
        public string TimePeriod { get; set; }
        public string Company { get; set; }
    
        public object Clone() => MemberwiseClone();
    }
    
    public class ComplexResume : ICloneable
    {
        private readonly WorkExperience _workExperience;
        private string _name;
        private string _email;
    
        public ComplexResume() => _workExperience = new WorkExperience();
    
        private ComplexResume(WorkExperience workExperience) => _workExperience = (WorkExperience)workExperience.Clone();
    
        public void SetPersonalInfo(string name, string email)
        {
            _name = name;
            _email = email;
        }
    
        public void SetWorkExperience(string comapny, string timePeriod)
        {
            _workExperience.Company = comapny;
            _workExperience.TimePeriod = timePeriod;
        }
    
        public void Show()
        {
            Console.WriteLine($"{_name} {_email}");
            Console.WriteLine($"Work Experience: {_workExperience.Company} {_workExperience.TimePeriod}");
        }
    
        public object Clone() => new ComplexResume(_workExperience)
        {
            _name = _name,
            _email = _email
        };
    }
    
    #region deep copy
    
    var complexResume = new ComplexResume();
    complexResume.SetPersonalInfo("xiaoming", "xiaoming@abc.xyz");
    complexResume.SetWorkExperience("xiaomingTecch", "2001~2005");
    complexResume.Show();
    
    var complexResume1 = (ComplexResume)complexResume.Clone();
    complexResume1.SetPersonalInfo("xiaohong", "xiaohong@abc.xyz");
    complexResume1.Show();
    
    #endregion deep copy
    

    More

    有人一定会说序列化了,当然,你用序列化也是可以做到的,序列化再反序列化得到的也是一个全新的对象,但是对于简单的对象,我觉得用上面这种方式就足够了,而且这种方式是直接操作内存,把对应的数据内存复制一份更加高效

    我们之前搞的推送服务里有一个推送请求的对象,会频繁的使用序列化反序列化来复制一个新的对象,这个场景就很适合使用原型模式来进行处理,高效的创建一个新的对象。

    在需要频繁的复制对象的场景下,都可以考虑使用原型模式来创建新的对象

    Reference

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    【HTML】添加网页背景音乐
    无线安全之破解WPA/WPA2 加密WiFi
    基于deepin-wine的windows软件打包deb安装包教程
    deepin V20 启用Nvidia驱动方法
    [Liunx]Linux安装screenfetch
    开往-友链接力
    linux常用命令(六)提权和文件上传下载的操作
    抓住会员!奇点云DataNuza重大发布
    喜讯 | 奇点云入选「GMIC 2020 PRO 十佳新生代」榜单
    数据智能应用最终实现企业降本增效
  • 原文地址:https://www.cnblogs.com/weihanli/p/prototype-pattern.html
Copyright © 2011-2022 走看看