架构师_设计模式_创建型_原型模式
创建型模式就是前面大佬总结出 对象的创建 如何合理利用 最后得出来的一些解决方案
原型模式:对象>浅拷贝与深拷贝,与c#内存有关
使用条件:需要很多重复的对象 有两个维度,一个是一摸一样的对象,一个是不同的对象
一个学生类,那么如果有十几万的学生类呢,不可能实例化十几万个吧,于是就有原型模式,可以浅拷贝十几万个学生对象 但指向内存的值是一样的,最新的会覆盖最前面的
也可以存在十几万个不同样的学生,深拷贝
比如现在有一个学生对象,我们实例化它的时候要两秒钟
(前面代码是类,后面代码放在 static void Main(string[] args){}里面执行)
public class Student { public int Id { get; set; } public string Name { get; set; } public Student() { Thread.Sleep(2000); //创建一个类型耗时要2秒 Console.WriteLine($"{this.GetType().Name}被构造.." ); } public void ShowName() { Console.WriteLine($"显示:{this.Name}"); } }
static void Main(string[] args) { {//垃圾写法 在循环里面实例化对象 五个就要十秒 //for (int i = 0; i <= 5; i++) //{ // Student student = new Student() { Id = 1, Name = "20200513DG" }; // student.ShowName(); //} } { //正常写法 student只需要实例化一次 //Student student = new Student(); //for (int i = 0; i <= 5; i++) //{ // student.Id = i; // student.Name = "1"; // student.ShowName(); //}
} }
如果别的地方要用这个对象呢,那么就是复制黏贴 这就叫做对象复用,但是如果需要几十万个相同的对象呢,难道生成几十万个实例?所以考虑到单例模式
/// <summary> /// 单例模式 /// </summary> public class StudentSingleton { public int Id { get; set; } public string Name { get; set; } /// <summary> /// 私有的静态字段--内存唯一,不会释放,且在第一次使用这个类被初始化且只初始化一次 /// </summary> private static StudentSingleton _Student = new StudentSingleton() { Id = 1, Name = "1" }; /// <summary> /// 1 构造函数私有化--避免随意构造 /// </summary> private StudentSingleton() { Thread.Sleep(2000); Console.WriteLine("{0}被构造..", this.GetType().Name); } /// <summary> /// 公开的静态方法来提供实例 /// </summary> /// <returns></returns> public static StudentSingleton CreateInstance() { return _Student; } } { //单例模式 for (int i = 0; i < 5; i++) { StudentSingleton student = StudentSingleton.CreateInstance(); student.Id = 1; student.Name = "1"; StudentSingleton student2 = StudentSingleton.CreateInstance(); student2.Id = 2; student2.Name = "2"; Console.WriteLine($"Hello World!{ student2.Id}"); 问题:此时用的是单例模式,那么 student和student2输出是什么
答案是:22 22 后面实例化的值都会覆盖前面的 因为是单例模式在整个进程中 都只会有一个实例,不可能出现两个--后面会覆盖前面的
用内存来讲 刚开始student 分配了一块内存,进程堆id=1 name=1 值在进程栈, string name 在堆里面 后面sudetn2实例化 只是把student的引用复制过来,实际存在进程栈的值是一样的
} }
需求又来了,几十万用户,难道都公用一个啊
namespace 原型模式 { /// <summary> /// 原型类 /// </summary> public class StudentPrototype { /// <summary> /// 构造函数私有化--避免随意构造 /// </summary> private StudentPrototype() { Thread.Sleep(2000); long lResult = 0; for (int i = 0; i < 1000000; i++) {//模拟耗时 lResult += i; } Console.WriteLine("{0}被构造..", this.GetType().Name); } /// <summary> /// 3 私有的静态字段--内存唯一,不会释放,且在第一次使用这个类被初始化且只初始化一次 /// </summary> private static StudentPrototype _Student = new StudentPrototype() { Id = 0, Name = "0", Class = new Class() { ClassId = 0, ClassName = "00" } }; /// <summary> /// 公开的静态方法来对外提供实例 /// </summary> /// <returns></returns> public static StudentPrototype CreateInstance() { //MemberwiseClone:内存拷贝,不走构造函数,直接内存copy,所以没有性能损失;而且产生的是新对象----浅拷贝--只拷贝引用 StudentPrototype student = (StudentPrototype)_Student.MemberwiseClone(); //深拷贝方式:1 直接new 2:子类型提供原型方式 //把引用的地址重新赋值,完成了深copy--不仅拷贝引用,还得拷贝引用类型的值 //student.Class = new Class() //{ // ClassId = student.Class.ClassId, // ClassName = student.Class.ClassName //}; return student; } public int Id { get; set; } public string Name { get; set; } public Class Class { get; set; } public void Study() { Console.WriteLine($"{this.Name}:{this.Id}:{this.Class.ClassId}:{this.Class.ClassName} "); } } public class Class { public int ClassId { get; set; } public string ClassName { get; set; } } } {//现在需求来了,有个平台 几十万用户,他们VIP等级不一样,显示的东西不一样,但是VIP对象难道要实例化几十万个吗,但是用单例模式后面又会覆盖前面的 //原型模式解决你的烦恼 Console.WriteLine("***************Prototype**************"); StudentPrototype student1 = StudentPrototype.CreateInstance(); StudentPrototype student2 = StudentPrototype.CreateInstance(); StudentPrototype student3 = StudentPrototype.CreateInstance(); student1.Id = 1; student1.Name = "1"; student1.Class.ClassId = 1; student1.Class.ClassName = "11"; //因为string类型的 ="1" 等同于 new String("1"); -----实际上string是不可修改的 student2.Id = 2; student2.Name = "2"; student2.Class.ClassId = 2; student2.Class.ClassName = "22"; //上面student1 和student1是浅拷贝,后面的会覆盖前面的,实际就是 1和2的class虽然是两个对象 但是他们只是引用不同,真正引用到的值还是相同的 student3.Id = 3; student3.Name = "3"; student3.Class = new Class() {//深拷贝 ClassId = 3, ClassName = "33" }; student1.Study(); student2.Study(); student3.Study(); //student1 student2 student3的 Class.ClassId的值 的输出是什么? 输出是223
为什么 因为 student1和2 是浅拷贝 支付引用的copy student3是深拷贝,完全复制出一个出来//C#内存分 进程堆(进程唯一)-----线程栈(每个线程一个)线程是可能会被销毁的 //引用类型在堆里,值类型在栈里---变量都在栈里 //引用类型对象里面的值类型---student1.Id 堆还是栈?---在堆里 //值类型里面的引用类型---Custom.Name 堆还是栈?----在堆里(任何引用类型的值都在堆里) }
本文来自博客园,作者:12不懂3,转载请注明原文链接:https://www.cnblogs.com/LZXX/p/12881084.html