• 架构师_设计模式_创建型_原型模式


    创建型模式就是前面大佬总结出  对象的创建 如何合理利用  最后得出来的一些解决方案

    原型模式:对象>浅拷贝与深拷贝,与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 堆还是栈?----在堆里(任何引用类型的值都在堆里) }
  • 相关阅读:
    框架比较
    框架整理
    bootstrap-table中get请求携带的参数
    0514任务思路
    两台电脑对码云上面的项目进行迭代
    项目问题
    vue 中发送axios请求,解决跨域问题(没有config文件)
    正则表达式(未完待续)
    【转载】深入理解Linux文件系统
    浅谈IO优化
  • 原文地址:https://www.cnblogs.com/LZXX/p/12881084.html
Copyright © 2020-2023  润新知