原型模式
原型模式(Prototype Pattern)

是用于创建重复的对象,同时又能保证性能。

(专门用来批量生成对象。)

namespace Learn.DesignerPattern.PrototypePattern
{
    /// <summary>
    /// 普通类型--实现原型
    /// </summary>
    public class PrototypeClass
    {
        /// <summary>
        /// 构造函数好事资源--关闭实例化
        /// </summary>
        public PrototypeClass()
        {
            long lResult = 0;
            for (int i = 0; i < 10000000; i++)
            {
                lResult += i;
            }
            Thread.Sleep(2000);
            Console.WriteLine($"{this.GetType().Name}被构造一次{Thread.CurrentThread.ManagedThreadId}");
        }

        /// <summary>
        /// 静态字段,在程序第一次使用这个类型之前,由CLR调用且只调用一次--非常适合初始化
        /// </summary>
        private static PrototypeClass _Instance = new PrototypeClass();

        public static PrototypeClass CreateInstance()
        {
            return _Instance;
        }

        public int Id { get; set; }
        public string? Name { get; set; }

        public void Show()
        {
            Thread.Sleep(100);
            //Console.WriteLine($"This is {this.GetType().Name}{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine($"this is {this.Id} {this.Name}");
        }

    }
}
namespace Learn.DesignerPattern.PrototypePattern
{
    public class PrototypeProgram
    {
        public static void Show()
        {
            { 
                //从单例到原型
                //创建重复对象,还要保证性能
                PrototypeClass prototype1 = PrototypeClass.CreateInstance();
                prototype1.Id = 123;
                prototype1.Name = "pamper";
                prototype1.Show();

                PrototypeClass prototype2 = PrototypeClass.CreateInstance();
                prototype2.Id = 345;
                prototype2.Name = "Haiyu";
                prototype2.Show();

                prototype1.Show();

                Console.WriteLine("全部创建成功");
            }
            { 
                //引用类型问题
            }
            { 
                //string问题
            }
        }
    }
}

因为是单例-----进程中只有一个实例-----所以操作的都是一个对象 

又得是不同的对象,还要保证速度--内存复制

        public static PrototypeClass CreateInstance()
        {
            PrototypeClass instance =(PrototypeClass)_Instance.MemberwiseClone();
            return instance;
        }

引用类型和浅拷贝引发的问题

namespace Learn.DesignerPattern.PrototypePattern
{
    /// <summary>
    /// 普通类型--实现原型
    /// </summary>
    public class PrototypeClass
    {
        /// <summary>
        /// 构造函数好事资源--关闭实例化
        /// </summary>
        public PrototypeClass()
        {
            long lResult = 0;
            for (int i = 0; i < 10000000; i++)
            {
                lResult += i;
            }
            Thread.Sleep(2000);
            Console.WriteLine($"{this.GetType().Name}被构造一次{Thread.CurrentThread.ManagedThreadId}");
        }

        /// <summary>
        /// 静态字段,在程序第一次使用这个类型之前,由CLR调用且只调用一次--非常适合初始化
        /// </summary>
        private static PrototypeClass _Instance = new PrototypeClass()
        {
            Id = 1,
            Name = "小勇",
            StudentClass = new StudentClass()
            {
                ClassId = 9,
                ClassName = "中级班"
            }
        };

        public static PrototypeClass CreateInstance()
        {
            PrototypeClass instance =(PrototypeClass)_Instance.MemberwiseClone();
            return instance;
        }

        public int Id { get; set; }
        public string? Name { get; set; }
        public StudentClass StudentClass { get; set; }

        public void Show()
        {
            Thread.Sleep(100);
            //Console.WriteLine($"This is {this.GetType().Name}{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine($"this is {this.Id} {this.Name}");
        }

    }
}

/// <summary>
/// 班级
/// </summary>
public class StudentClass
{
    public int ClassId { get; set; }
    public string? ClassName { get; set; }

    public void StudentShow()
    {
        Console.WriteLine($"this is {this.ClassId} {this.ClassName}");
    }
}
        public static PrototypeClass CreateInstance()
        {
            PrototypeClass instance = (PrototypeClass)_Instance.MemberwiseClone();//拷贝引用

            instance.StudentClass = new StudentClass()
            {
                ClassId = _Instance.StudentClass.ClassId,
                ClassName = _Instance.StudentClass.ClassName
            };//还可以通过序列化反序列化方式做深拷贝

            return instance;
        }

namespace Learn.DesignerPattern.PrototypePattern
{
    public class PrototypeProgram
    {
        public static void Show()
        {
            { 
                ////从单例到原型
                ////创建重复对象,还要保证性能
                //PrototypeClass prototype1 = PrototypeClass.CreateInstance();
                //prototype1.Id = 123;
                //prototype1.Name = "pamper";
                //prototype1.Show();

                //PrototypeClass prototype2 = PrototypeClass.CreateInstance();
                //prototype2.Id = 345;
                //prototype2.Name = "Haiyu";
                //prototype2.Show();

                //prototype1.Show(); //因为是单例---进程中只有一个实例---所以操作的都是一个对象

                ////又得是不同的对象,还要保证速度--内存复制


                //Console.WriteLine("全部创建成功");
            }
            {
                //引用类型问题
                PrototypeClass prototype1 = PrototypeClass.CreateInstance();
                prototype1.Id = 123;
                prototype1.Name = "pamper";
                prototype1.StudentClass.ClassId = 1;
                prototype1.StudentClass.ClassName = "中级班";

                prototype1.Show();
                prototype1.StudentClass.StudentShow();

                PrototypeClass prototype2 = PrototypeClass.CreateInstance();
                prototype2.Id = 345;
                prototype2.Name = "Haiyu";
                prototype2.StudentClass.ClassId = 2;
                prototype2.StudentClass.ClassName = "高级班";
                prototype2.Show();
                prototype2.StudentClass.StudentShow();

                prototype1.Show(); 
                prototype1.StudentClass.StudentShow();
                //引用类型+浅拷贝---只拷贝了引用,所以对象共享,所以会覆盖
                //解决办法:深拷贝---拷贝值
            }
            { 
                //string问题
            }
        }
    }
}

这样就不会覆盖

补充:

string是不是引用类型?---是的---但是string没有特殊处理?
原因是string类型是不可变的,每次赋值其实都是开辟新空间,替换引用,所以不会覆盖。
不可变的原因---为了避免内存的频繁移动----然后又开启了享元模式。

创建一个对象有哪几种方式:

  • 直接new一下;
  • 单例;
  • 原型;
  • 三大工厂 ----- 就是转移对象的创建;
  • 建造者 ----- 更复杂的工厂方法;

设计模式总结:

创建型:花样new---关注对象的创建

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐