网站 not found,互联网创新创业项目计划书案例,中小企业 网站建设,做自己的建材配送网站原型模式 (Prototype Pattern)
原型模式 (Prototype Pattern) 是一种创建型设计模式#xff0c;它允许通过复制现有的对象来创建新对象#xff0c;而不是通过直接实例化类。这意味着你可以通过克隆原型对象来生成新的实例#xff0c;而不必依赖类的构造函数。该模式的核心思…原型模式 (Prototype Pattern)
原型模式 (Prototype Pattern) 是一种创建型设计模式它允许通过复制现有的对象来创建新对象而不是通过直接实例化类。这意味着你可以通过克隆原型对象来生成新的实例而不必依赖类的构造函数。该模式的核心思想是通过创建一个对象的副本即原型来避免昂贵的初始化操作。
在 C# 中通常通过实现 ICloneable 接口或者自定义的克隆方法来实现原型模式。
1、原型模式的原理 原型模式的工作原理是
定义一个原型接口或基类用来提供克隆的方法如 Clone。 具体的类实现该接口提供自己的克隆方法该方法返回当前对象的深拷贝或浅拷贝。 客户端可以通过克隆原型对象来创建新对象而无需知道如何构造对象。 拷贝的类型可以分为
浅拷贝 (Shallow Copy)只复制对象的基本数据类型对于引用类型的字段只复制引用地址。深拷贝 (Deep Copy)不仅复制对象的所有值还递归地复制所有引用对象创建独立的副本。
2、什么时候使用原型模式
需要频繁创建相似对象时如果系统需要创建大量相似或结构复杂的对象时通过克隆原型对象来生成新对象可以提高性能。对象的创建代价高昂时如果对象的初始化非常复杂包含很多属性设置或涉及昂贵的资源操作如网络连接、文件系统操作使用原型模式避免了重复创建过程。避免对象过多的子类化当不希望为了创建新对象而引入更多的子类或扩展类时原型模式可以避免通过继承创建不同类型对象的繁琐过程。需要保存对象的历史状态或备份时如果需要将某个对象的状态备份或在某个时刻进行复制如撤销操作、快照功能可以通过原型模式来克隆对象。
3、使用原型模式的好处
提高对象创建效率对于某些对象的创建过程非常复杂或耗时时通过克隆现有对象即原型可以避免重复的复杂初始化节省时间和资源。原型模式向客户隐藏了创建新实例的复杂性原型模式允许动态增加或较少产品类。原型模式简化了实例的创建结构工厂方法模式需要有一个与产品类等级结构相同的等级结构而原型模式不需要这样。产品类不需要事先确定产品的等级结构因为原型模式适用于任何的等级结构
4、使用原型模式的注意事项 克隆的深浅拷贝对于引用类型字段使用浅拷贝时需要特别小心浅拷贝只复制引用而不复制对象本身可能导致两个对象共用同一份数据。若需要完全独立的对象必须使用深拷贝。
复杂对象的克隆当对象包含复杂的嵌套结构或其他依赖时确保实现合适的深拷贝逻辑否则可能会出现数据共享或数据覆盖问题。
性能考虑尽管原型模式避免了对象的重复构造但深拷贝可能引入较大的性能开销特别是在对象嵌套复杂时。因此在性能敏感的场景下要慎重考虑深拷贝的实现。
原型的可变性当通过原型模式创建对象时如果不慎修改了原型本身的状态所有基于该原型创建的对象也可能受到影响。因此在设计时需要确保原型对象的状态是安全的。
总之原型模式 通过复制现有对象来生成新对象避免了类构造的开销特别适用于对象创建代价高昂或需要动态创建对象的场景。它提供了灵活的对象创建方式减少了类的复杂性和耦合度。使用时需要根据具体需求选择浅拷贝或深拷贝并确保对象的可复制性和独立性。
在 Unity 中使用 原型模式
在 Unity 中原型模式可以应用于场景中需要频繁生成的对象比如 3D 模型如立方体、球体等。通过原型模式我们可以避免每次都从头实例化对象而是通过复制现有的对象来创建新的实例。
我们将创建几个简单的原型模式应用 用于克隆 Unity 中的 3D 对象立方体、球体等并根据用户输入生成多个克隆对象。 步骤 创建一个基类 ShapePrototype它提供克隆接口。创建不同的形状类如立方体和球体继承自 ShapePrototype。使用原型模式通过克隆现有对象来创建新对象而不是直接创建新对象。 1.定义基类 ShapePrototype
using UnityEngine;// 定义一个抽象的原型基类
public abstract class ShapePrototype : MonoBehaviour
{// 定义一个抽象的克隆方法public abstract ShapePrototype Clone();// 通用的显示形状信息的方法public abstract void DisplayInfo();
}
2.创建具体的形状类
2.1立方体类
using UnityEngine;public class Cube : ShapePrototype
{// 重写克隆方法public override ShapePrototype Clone(){// 实现浅拷贝复制当前对象的属性GameObject clone Instantiate(this.gameObject);return clone.GetComponentShapePrototype();}public override void DisplayInfo(){Debug.Log(This is a Cube.);}
}
2.2球体类
using UnityEngine;public class Sphere : ShapePrototype
{// 重写克隆方法public override ShapePrototype Clone(){// 实现浅拷贝复制当前对象的属性GameObject clone Instantiate(this.gameObject);return clone.GetComponentShapePrototype();}public override void DisplayInfo(){Debug.Log(This is a Sphere.);}
}
3.创建ShapeSpawner 负责克隆对象
using UnityEngine;public class ShapeSpawner : MonoBehaviour
{public ShapePrototype cubePrototype; // 立方体原型public ShapePrototype spherePrototype; // 球体原型private void Update(){// 按下 C 键克隆立方体if (Input.GetKeyDown(KeyCode.C)){ShapePrototype cubeClone cubePrototype.Clone();cubeClone.transform.position new Vector3(Random.Range(-5, 5), 1, Random.Range(-5, 5));cubeClone.DisplayInfo();}// 按下 S 键克隆球体if (Input.GetKeyDown(KeyCode.S)){ShapePrototype sphereClone spherePrototype.Clone();sphereClone.transform.position new Vector3(Random.Range(-5, 5), 1, Random.Range(-5, 5));sphereClone.DisplayInfo();}}
}
4.设置场景中的原型对象
创建一个 Unity 场景并添加一个空物体 ShapeSpawner将上面的 ShapeSpawner 脚本挂载到该物体上。在场景中创建一个立方体和一个球体并将它们的 Cube 和 Sphere 脚本分别挂载到立方体和球体上。在 ShapeSpawner 脚本的 cubePrototype 和 spherePrototype 变量中分别拖拽场景中的立方体和球体作为原型对象。
5.输出查看结果
这种模式在 Unity 的游戏开发中非常适合用于生成大量相似对象如敌人、物品、特效等。 克隆一个新对象然后将当前对象非静态字段克隆到该新对象
1.定义基类 Prototype
public abstract class Prototype
{private string id;public Prototype(string id){this.id id;}public string Id{get { return id; }}//抽象类关键有这样一个Clone方法public abstract Prototype Clone();
}
2.创建具体原型ConcretePrototypel类
class ConcretePrototypel : Prototype
{public ConcretePrototypel(string id) : base(id) { }public override Prototype Clone(){//创建一个新对象然后将当前对象非静态字段复制到该新对象//如果字段是值类型则逐位复制字段引用类型只复制引用地址return (Prototype)this.MemberwiseClone();}
}
3.创建main脚本负责克隆对象
class Main : MonoBehaviour
{private void Start(){ConcretePrototypel pl new ConcretePrototypel(I);ConcretePrototypel cl (ConcretePrototypel)pl.Clone();Debug.Log(clone cl.Id);}
}
4.输出查看结果
由于克隆实在太常用.Net在System命名空间提供了IClone接口唯一的Clone()方法只要实现这个接口就可以完成原型模式了。 简历类用于克隆 Unity 中的 个人信息
1.创建简历基础脚本
class Resume : ICloneable
{private string name;private string sex;private string age;private string timearea;private string company;public Resume(string name){this.name name;}//设置个人信息public void SetPersonalInfo(string sex,string age){this.sex sex;this.age age;}//设置工作经历public void SetWorkExperrience(string timeArea,string company){this.timearea timeArea;this.company company;}//显示public void Display(){//实现接口方法克隆对象Debug.Log(name sex age);Debug.Log(timearea company);}public object Clone(){return (object)this.MemberwiseClone();}
}
2.克隆新简历并修改简历中的个人信息
class Main : MonoBehaviour
{private void Start(){Resume a new Resume(DJ);a.SetPersonalInfo(男, 22);a.SetWorkExperrience(1995-2022, DJDJ);//调用克隆方法就可以实现新简历并且可以修改新简历细节Resume b (Resume)a.Clone();b.SetPersonalInfo(nv, 20);Resume c (Resume)a.Clone();c.SetWorkExperrience(1999-2222, JJJJ);a.Display();b.Display(); c.Display();}
}
3.输出查看结果
现实设计当中一般会再有一个“工作经历”类当中有“时间区间”和“公司名称”等属性“简历”类直接调用。
class Resume : ICloneable
{private string name;private string sex;private string age;private WorkExperience work;///引用“工作经历”对象public Resume(string name){this.name name;work new WorkExperience();//简历实例化同时实例化工作经历}public void SetPersonalInfo(string sex,string age){this.sex sex;this.age age;}public void SetWorkExperrience(string workDate,string company){work.WorkDate workDate;//调用方法给对象赋值work.Company company;}public void Display(){Debug.Log(name sex age);Debug.Log(work.WorkDate work.Company);//显示工作经历属性值}public object Clone(){return (object)this.MemberwiseClone();}
}
class WorkExperience
{private string workDate;public string WorkDate{get { return workDate; }set { workDate value; }}private string company;public string Company{get { return company; }set { company value; }}
}
使用之前的客户端逻辑输出查看结果
对于引用类型克隆后没有实现真正的克隆而是只克隆了引用地址这叫做“浅复制”被复制对象的所有变量都含有与原来的对象相同的值;而所有的对其他对象的引用都仍然指向原来的对象。
深复制把引用对象的变量指向复制过的新对象而不是原有的被引用的对象。
深复制流程
1.首先修改WorkExperience类增加克隆方法
class WorkExperience
{private string workDate;public string WorkDate{get { return workDate; }set { workDate value; }}private string company;public string Company{get { return company; }set { company value; }}public object Clone(){//工作经历类也实现克隆方法return (object)MemberwiseClone();}
}
2.然后修改简历类新增构造函数方便克隆工作经历类再修改简历类的克隆方法
class Resume : ICloneable
{private string name;private string sex;private string age;private WorkExperience work;public Resume(string name){this.name name;work new WorkExperience();}//提供Clone方法调用的私有构造函数以便克隆工作经历数据public Resume(WorkExperience work){this.work (WorkExperience)work.Clone();}public void SetPersonalInfo(string sex,string age){this.sex sex;this.age age;}public void SetWorkExperrience(string workDate,string company){work.WorkDate workDate;work.Company company;}public void Display(){Debug.Log(name sex age);Debug.Log(work.WorkDate work.Company);}//调用私有构造方法让工作经历克隆然后再给新对象其他字段赋值//最终返回一个深复制的简历对象public object Clone(){Resume obj new Resume(this.work);obj.name this.name;obj.sex this.sex; obj.age this.age;return obj;}
}
3.输出查看结果 今天是2024年11月24日
重复一段毒鸡汤来勉励我和你
你的对手在看书
你的仇人在磨刀
你的闺蜜在减肥
隔壁的老王在练腰
而你在干嘛