Unity【话大】设计模式之原型模式

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 前言:笔者在最开始写程序的时候经常会遇到一种情况,例如更改一个字段、或者添加一种小功能,就要把原来写过的东西几乎废弃掉,或者更改大量以前写过的代码。又或者自己写的东西时间久了再去回顾,完全找不到到时为什么这么写的头绪,如果遇到了Bug更是无法快速定位在哪里小范围出现的问题。

前言:笔者在最开始写程序的时候经常会遇到一种情况,例如更改一个字段、或者添加一种小功能,就要把原来写过的东西几乎废弃掉,或者更改大量以前写过的代码。又或者自己写的东西时间久了再去回顾,完全找不到到时为什么这么写的头绪,如果遇到了Bug更是无法快速定位在哪里小范围出现的问题。如果你也经常遇到这种问题,就说明你现阶段非常需要学习下设计模式了

在网上经常说的设计模式有23种,也有一些更多的设计模式,无非也是从这些设计模式中变种而来。如果让笔者来形容什么是设计模式,我认为设计模式是:一种思想,一种模式,一种套路,一种解决问题的高效策略



有说的不正确或者不准确的地方欢迎留言指正


有什么有趣的写作技巧或者想法欢迎大家给我留言,大家的帮助是我写下去最有效的动力



img_c6f98d93ec2b7f2e0f49e687460e6ca4.jpe

细胞分裂这个概念大家应该都知道,一个细胞,从自己的内部慢慢酝酿生成另一个和自己一模一样的个体,当生产完全时,会从原来的本体剥离,变成2个一模一样的细胞,这种以本体为原型,从内部生产另外一个一模一样实体的行为在设计模式中也有相应的表现,那就是笔者今天要跟大家介绍的原型模式

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

参考链接

示例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Custom.Log;
using System.Threading;

public class LifeCycleLog: ICloneable
{
    public string description;

    public object Clone()
    {
        return MemberwiseClone();
    }
}
public class Cell:ICloneable
{
    public int id;
    public string name;
    public LifeCycleLog lifeCycleLog;

    public Cell(int tempID,string tempName)
    {
        this.id = tempID;
        this.name = tempName;
        lifeCycleLog = new LifeCycleLog();
        Thread.Sleep(1000);
    }

    public object Clone()
    {
        Cell tempCell = new Cell(this.id, this.name);
        tempCell.lifeCycleLog.description = lifeCycleLog.description;
        return tempCell;
    }
    public void Log()
    {
        this.Log($"细胞ID:{id},细胞名称:{name},日志:{lifeCycleLog.description}");
    }
}![2.gif](https://upload-images.jianshu.io/upload_images/7643202-987c70b99206d626.gif?imageMogr2/auto-orient/strip)

调用

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Custom.Log;
using System.Threading;
using System.Threading.Tasks;
public class PrototypePatternComponent : MonoBehaviour
{
    void Start()
    {
        Task.Run(() => 
        {
            Cell Cell = new Cell(0, "编号00");
            Cell.lifeCycleLog.description = "生命周期日志00";
            Cell.Log();
            this.Log("【准备复制】");
            Thread.Sleep(500);

            for (int i = 0; i < 5; i++)
            {
               Cell tempCell =  (Cell)Cell.Clone();
                tempCell.Log();
            }
            this.Log("【复制完毕】");
        });
    }
}

打印日志

img_45cec2d1e87982031cd63136b15bac3e.gif

这样我们最粗糙的原型模式就算是完成了,是不感觉很简单呢。但是为什么说粗糙呢?因为还有更有效的拷贝方式,那当然要用C#自带的MemberwiseClone函数啦。我们只需要继承ICloneable接口将原来的Clone函数稍加改动即可,速度快的飞起~

    public object Clone()
    {
        return MemberwiseClone();
    }

打印日志

img_88798d4583a5a81416168f2e6b3e7518.gif

MemberwiseClone函数对应的文档中我们知道,他这种复制属于浅复制,在这里笔者就要引入两个概念了,浅拷贝深拷贝

首先我们先从一个示例看什么是浅拷贝和深拷贝

示例代码

    void Start()
    {
        Cell cell = new Cell(0, "编号00");
        cell.lifeCycleLog.description = "生命周期日志00";

        Cell cell01 = (Cell)cell.Clone();
        cell01.id = 1;
        cell01.name = "编号01";
        cell01.lifeCycleLog.description = "改动后的生命周期日志";

        cell.Log();
        cell01.Log();
    }

打印信息

img_9b454c33ed10d1af76d7417e5670c463.png

大家应该会发现,笔者只更改了cell01中的lifeCycleLog的描述,但是所有的描述都进行了更改,因为这就是使用了浅拷贝的缘故。

浅拷贝

浅复制正在创建一个新对象,然后将当前对象的非静态字段复制到新对象。如果字段是值类型 - >执行字段的逐位复制; 对于引用类型 - >复制引用,但不复制引用对象; 因此原始对象及其克隆引用相同的对象。 在C#和VB.NET中,浅层复制由对象MemberwiseClone()方法完成。

img_05b313cf15ca0e2a0b13ab97d3cc986d.png

深拷贝

深层复制正在创建一个新对象,然后将当前对象的非静态字段复制到新对象。如果字段是值类型 - >执行字段的逐位复制。如果字段是引用类型 - >执行引用对象的新副本。

img_7baec25826ef08d53f466c95577c344e.png

不知道这回大家是否明白为什么会造成lifeCycleLog描述一致的原因呢?最初笔者曾认为浅拷贝是Cell cell01 = cell;这种形式的23333~现在看并没有那么“浅”。但是又有同学会表示疑问,string类型也是引用类型,而且stirng有这种特殊的享元模式,他问什么没有一同改变呢?这个要从string的定义来看了。string本质是只读的,所以有任何的更改都会创建一个新的副本。所以string这种引用类型并不会一起改变。

img_a3b73702db87d6bd03c0f4bdbb00f6f3.png

所以说需要深拷贝的话我们可以这么写,既保证了速度又进行了深度的拷贝。

    public object DeepClone()
    {
        Cell tempCell = (Cell)MemberwiseClone();
        tempCell.lifeCycleLog = (LifeCycleLog)this.lifeCycleLog.Clone();
        return tempCell;
    }

打印日志

img_4abb28eff402ab99b6c4b3426a2bb125.png

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

当然深拷贝还有以下几种方式

如果大家在项目中有这种需要实例化多个一样的类且初始化比较耗时的需求时,原型模式是个不错的选择~

img_569463b7983f645f063dd7b1bef93e0c.png
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
6月前
|
设计模式 安全 Java
面向对象编程的精髓:Java设计模式 - 原型模式(Prototype)完全参考手册
【4月更文挑战第7天】原型模式是OOP中的创建型设计模式,用于通过复制现有实例创建新实例,尤其适用于创建成本高或依赖其他对象的情况。它包括Prototype接口、ConcretePrototype实现和Client客户端角色。优点是性能优化、避免子类化和动态增加产品族。实现包括定义原型接口、实现具体原型和客户端调用克隆方法。最佳实践涉及确保克隆正确性、选择深拷贝或浅拷贝及考虑线程安全。但需注意克隆方法管理、性能开销和循环引用等问题。在Java中,实现Cloneable接口和覆盖clone方法可实现原型模式。
73 4
|
6月前
|
设计模式 Java 关系型数据库
23种设计模式 —— 原型模式【克隆羊、浅拷贝、深拷贝】
23种设计模式 —— 原型模式【克隆羊、浅拷贝、深拷贝】
|
6月前
|
设计模式 安全 Java
【设计模式】原型模式
【设计模式】原型模式
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
2月前
|
设计模式 Java
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
|
4月前
|
设计模式
iLogtail设计模式问题之iLogtail中的原型模式是什么
iLogtail设计模式问题之iLogtail中的原型模式是什么
iLogtail设计模式问题之iLogtail中的原型模式是什么
|
4月前
|
设计模式 JavaScript
js设计模式【详解】—— 原型模式
js设计模式【详解】—— 原型模式
49 6
|
5月前
|
设计模式 Java
Java设计模式之原型模式详解
Java设计模式之原型模式详解
|
5月前
|
设计模式
原型模式-大话设计模式
原型模式-大话设计模式
|
5月前
|
设计模式 Java Spring
设计模式——原型模式
设计模式——原型模式