设计模式-创建型-原型模式(ProtoType)

原型模式是通过复制已有对象来创建新对象,减少了初始化过程,提高性能。适用于大量复制且初始化复杂的场景。文章介绍了原型模式的基本实现和通过原型注册表的实现方式,展示了如何在C#中使用,并总结了其优点和缺点,包括可能增加内存占用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录



前言

原型模式的核心在于复制对象,首先创建一个对象,然后直接基于内存二进制流进行复制,不需要在耗时的去对象初始化的过程,针对于大批量操作以及复杂类的实例化性能提升很多,


一、原型模式(ProtoType)

定义某个对象为一个原型,根据这个原型来创建对象,减少了初始化的过程,性能提升很多。

二、应用场景

  • 针对大量get,set复制的情况,创建对象初始化的过程,可以提升效率。
  • 创建对象成本较大时,使用原型模式,比如建造者模式中,多个对象组合成一个大的结构。
  • 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性,
  • 系统中大量使用该类对象,且各个调用者都需要给他的属性重新复制时,

三、角色分析

  1. 客户(Client):客户类提出创建对象的请求
  2. 抽象原型(IProtoType):规定复制接口
  3. 具体原型(ConcreteProtoType):被复制的对象。

四、实现

1、基本实现

原型模式的基本实现方式。

2、原型注册表实现

提供了一种访问常用原型的简单方法, 其中存储了一系列可供随时复制的预生成对象。 最简单的注册表原型是一个 名称 → 原型的哈希表。 但如果需要使用名称以外的条件进行搜索, 你可以创建更加完善的注册表版本。

二、使用步骤

1.通用原型使用方式

通用原型使用方式

	/// <summary>
    /// 实体类
    /// </summary>
    public class CommonProtoType
    {
        public CommonProtoType(int age, string name, bool sex, string phone, string emain, string address, string password)
        {
            this.age = age;
            this.Name = name;
            this.sex = sex;
            this.Phone = phone;
            this.email = email;
            this.address = address;
            this.password = password;
        }
        public int age { get; set; }
        public string? Name { get; set; }
        public bool sex { get; set; }
        public string? Phone { get; set; }
        public string? email { get; set; }
        public string? address { get; set; }
        public string? password { get; set; }
        //获取克隆的新对象
        public CommonProtoType GetCloneNewObject()
        {
            return (CommonProtoType)this.MemberwiseClone();
        }

    }
    /// <summary>
    /// 客户端
    /// </summary>
    public class Client
    {
        public void testDemo()
        {
            var protoType = new CommonProtoType(10, "kenny", sex: true, phone: "123412341234", emain: "kenny@abp.com", address: "test.Kenny", password: "asdfasdf");
            var cloneProtoType = protoType.GetCloneNewObject();
            cloneProtoType.age = 20;


            Console.WriteLine(JsonConvert.SerializeObject(protoType));
            Console.WriteLine(JsonConvert.SerializeObject(cloneProtoType));
        }
    }

运行结果

{"age":10,"Name":"kenny","sex":true,"Phone":"123412341234","email":null,"address":"test.Kenny","password":"asdfasdf"}
{"age":20,"Name":"kenny","sex":true,"Phone":"123412341234","email":null,"address":"test.Kenny","password":"asdfasdf"}

2.原型注册表实现

代码如下(示例):接上面CommonProtoType实体类,增加下面仓库管理以及仓库客户端类。

    /// <summary>
    /// 仓库管理类
    /// </summary>
  public class ProtoTypeRepository
    {
        public static Dictionary<string, object> repository = new Dictionary<string, object>();
        public static void insert(string key, object value)
        {
            repository.Add(key, value);
        }
        public static object getValueByKey(string key)
        {
            return repository.Where(p => p.Key.Equals(key)).FirstOrDefault().Value;
        }
    }
    /// <summary>
    /// 仓库客户端
    /// </summary>
    public class repositoryClient
    {
        public void testDemo()
        {
            Console.WriteLine("第一次创建对象的实例");
            var protoType = new CommonProtoType(10, "kenny", sex: true, phone: "123412341234", emain: "kenny@abp.com", address: "test.Kenny", password: "asdfasdf");
            Console.WriteLine("将对象的实例保存到仓库");
            ProtoTypeRepository.insert("CommonProtoType", protoType);
            Console.WriteLine("需要使用时从仓库读取出对应的实例,然后克隆出新的实例");
            var outObject = (CommonProtoType)ProtoTypeRepository.getValueByKey("CommonProtoType");
            var newObject=outObject.GetCloneNewObject();
            Console.WriteLine("得到新实例修改值");
            newObject.age = 20;

            Console.WriteLine(JsonConvert.SerializeObject(protoType));
            Console.WriteLine(JsonConvert.SerializeObject(outObject));
            Console.WriteLine(JsonConvert.SerializeObject(newObject));
        }
    }

输出内容

第一次创建对象的实例
将对象的实例保存到仓库
需要使用时从仓库读取出对应的实例,然后克隆出新的实例
得到新实例修改值
{"age":10,"Name":"kenny","sex":true,"Phone":"123412341234","email":null,"address":"test.Kenny","password":"asdfasdf"}
{"age":10,"Name":"kenny","sex":true,"Phone":"123412341234","email":null,"address":"test.Kenny","password":"asdfasdf"}
{"age":20,"Name":"kenny","sex":true,"Phone":"123412341234","email":null,"address":"test.Kenny","password":"asdfasdf"}


总结

优点:

  • 针对于需要频繁创建对象的方法可以有效的提高运行效率,减少对象初始化时间。

缺点:

  • 需要为每个可以被克隆的类提供一个克隆方法。
  • clone方法位于类内部,当对已有代码进行改造的时候,需要修改代码,违背了开闭原则。
  • 当不适用时仓库原型模式会长期占用内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kenny@chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值