赞
踩
原型模式能够让你复制已有的对象(字段复制),且不会使代码产生依赖的类。
原型模式说白了就是克隆,让你可以克隆你想克隆的类。这种克隆是动态的,是根据现有的模板克隆的,属性是完全一致的。
说明
Clone()
抽象方法,需要克隆的对象只需实现这个接口即可。ICloneable
,实现方法Clone()
即可,此接口就是立即可用的原型模式,非常方便。实现方法
浅拷贝
:克隆对象时,字段中的引用类型只拷贝其地址,而不是重新 new 一个新的类。(如果克隆的类中有引用类型,则克隆出来的类的引用类型,它们的引用类型相同,即引用类型声明的地址相同)
深拷贝
:克隆对象的值类型和引用类型都不同,但值是相同的。
如果一个类中只有值类型的字段,则使用浅拷贝即可,如果有引用类型,则需要注意,可能需要使用深拷贝。
public class PrototypeExample : MonoBehaviour
{
private void Start()
{
Enemy enemy = new Enemy("剑士", 1);
Enemy enemy1 = enemy.Clone() as Enemy;
Debug.Log("enemy : " + enemy.Name + " enemy1 : " + enemy.Name);
Debug.Log("enemy : " + enemy.ID + " enemy1 : " + enemy.ID);
//是否相等
Debug.Log(enemy == enemy1);
}
}
public class Enemy : ICloneable { private string _name; private int _id; public string Name => _name; public int ID => _id; public Enemy(string name, int id) { _name = name; _id = id; } public object Clone() { return this.MemberwiseClone() as Enemy; } }
说明:拷贝出来的类,是两个字段相同的类。
提示:当类的字段只有值类型 或 string 类型的时候,才应该使用浅拷贝。
public class GamePlayer : ICloneable { public string name; public Weapon weapon; public GamePlayer(string name, Weapon weapon) { this.name = name; this.weapon = weapon; } public object Clone() { GamePlayer clonePlayer = null; try { clonePlayer = this.MemberwiseClone() as GamePlayer; clonePlayer.weapon = new Weapon(weapon.weaponName, weapon.attackForce); } catch { Debug.Log("GamePlayer拷贝失败"); } return clonePlayer; } } public class Weapon { public string weaponName; public float attackForce; public Weapon(string weaponName, float attackForce) { this.weaponName = weaponName; this.attackForce = attackForce; } }
public class PrototypeExample1 : MonoBehaviour
{
private void Start()
{
GamePlayer player = new GamePlayer("宵", new Weapon("千云", 25.0f));
GamePlayer player1 = player.Clone() as GamePlayer;
Debug.Log(player == player1);
Debug.Log(player.weapon == player1.weapon);
Debug.Log(player1.name);
Debug.Log(player1.weapon.weaponName);
Debug.Log(player1.weapon.attackForce);
}
}
手动拷贝效率是深拷贝里最高的,如果类比较简单的话,尽量使用手动拷贝。
这里使用的 Json 类是 UnityEngine.JsonUtility
这是 Unity 官方自带的。
[Serializable] public class GamePlayer : ICloneable { public string name; public Weapon weapon; public GamePlayer(string name, Weapon weapon) { this.name = name; this.weapon = weapon; } public object Clone() { string jsonObj = JsonUtility.ToJson(this); GamePlayer clonePlayer = JsonUtility.FromJson<GamePlayer>(jsonObj); return clonePlayer; } } [Serializable] public class Weapon { public string weaponName; public float attackForce; public Weapon(string weaponName, float attackForce) { this.weaponName = weaponName; this.attackForce = attackForce; } }
public class PrototypeExample1 : MonoBehaviour
{
private void Start()
{
GamePlayer player = new GamePlayer("宵", new Weapon("千云", 25.0f));
GamePlayer player1 = player.Clone() as GamePlayer;
Debug.Log(player == player1);
Debug.Log(player.weapon == player1.weapon);
Debug.Log(player1.name);
Debug.Log(player1.weapon.weaponName);
Debug.Log(player1.weapon.attackForce);
}
}
结果与上面一样
Json 序列化和反序列化实现深拷贝十分方便。有一些细节需要注意
[Serializable]
特性UnityEngine.Object
类是不可以被序列化的提醒: Unity 中
游戏对象
和组件
的拷贝 - 使用Object.Instantiate()
函数即可
优点
缺点
原型模式的核心是克隆类,且不依赖于其他类。原型模式可以其他模式配合使用 。(如抽象工厂模式,可以通过预生成的类,进行克隆,满足需求)
谢谢 声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。