【23种GOF设计模式】C#代码完整案例详解--原型模式

来自:CCNetCore社区,一个关注.Netcore领域的社区团队。

原型模式PrototypePattern

原型模式PrototypePattern 创建型设计模式

用于对象的创建,通常用于单例模式中。
由于单例模式的对象始终为1个,又要用到单例模式又想每次调用有不一样的结果,可以使用原型模式。
添加一个创建实例的方法即可。
可通过内存复制或者with关键字进行浅拷贝
可通过序列化再反序列化进行深度拷贝

要区分一下值类型与引用类型。栈中存储变量,堆存储值。
string是一个特殊的引用对象,每次赋值时都会创建新的实例。

例如:单例模式中又想每次调用有不同结果,可使用原型模式。

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PrototypePattern
{
   /// <summary>
   /// 1 单例模式/原型模式/享元模式
   /// 2 浅克隆VS深克隆,原型模式的应用
   /// 3 C#内存分配机制详析
   /// 
   /// 设计模式:面向对象语言开发过程中,遇到种种场景和问题,提出的解决方案和思路,沉淀下来
   ///           ----设计模式 套路,解决问题的套路,站在前辈的肩膀上
   /// 创建型设计模式--关注对象的创建--new()--三大工厂+建造者+单例+原型
   /// 即使是一个简单的对象复用,都有很多招数--
   /// 
   /// 结构型设计模式
   /// 行为型设计模式
   /// 
   /// C#内存分配机制
   /// 
   /// 原型模式也就是用利用对象copy,快速获取对象---需要大量新对象的时候
   /// 
   /// 
   /// </summary>
   class Program
   {
       static void Main(string[] args)
       {
           try
           {
               Console.WriteLine("欢迎来到.net高级班公开课之设计模式特训,今天是Eleven老师为大家带来的原型模式Prototype");
               {
                   //Console.WriteLine("***************Common**************");
                   ////对象复用---循环的就最简单了---不同的方法/类/线程/类库--重用对象
                   //Student student = new Student()
                   //{
                   //    Id = 1121,
                   //    Name = "馒头哥"
                   //};
                   //for (int i = 0; i < 5; i++)
                   //{
                   //    //Student student = new Student()
                   //    //{
                   //    //    Id = 1121,
                   //    //    Name = "馒头哥"
                   //    //};
                   //    student.Study();
                   //}
               }
               {
                   //Console.WriteLine("***************Singleton**************");
                   ////挺熟悉单例的刷个1  不太熟悉刷个2
                   ////单例模式:保证整个进程中,该对象只有一个实例
                   //for (int i = 0; i < 5; i++)
                   //{
                   //    StudentSingleton student = StudentSingleton.CreateInstance();
                   //    student.Study();
                   //}
                   ////对单例不太熟悉的,建议加一下课堂的助教老师,获取单例课程的视频代码
               }
               {
                   //Console.WriteLine("***************Singleton**************");
                   //StudentSingleton student1 = StudentSingleton.CreateInstance();
                   //StudentSingleton student2 = StudentSingleton.CreateInstance();
                   //student1.Id = 234;
                   //student1.Name = "CodeMan";

                   //student2.Id = 345;
                   //student2.Name = "左耳听风";

                   //student1.Study();
                   //student2.Study();
                   ////单例---整个进程只有一个实例--能出现2个学生?不可能!---后面会覆盖前面的
               }
               {
                   //单例可以对象复用---但是会出现覆盖
                   //能不能不覆盖,但是性能也高?
                   //Console.WriteLine("***************Prototype**************");
                   //for (int i = 0; i < 5; i++)
                   //{
                   //    StudentPrototype student = StudentPrototype.CreateInstance();
                   //    student.Study();
                   //}
               }
               {
                   Console.WriteLine("***************Prototype**************");
                   StudentPrototype student1 = StudentPrototype.CreateInstance();
                   StudentPrototype student2 = StudentPrototype.CreateInstance();
                   StudentPrototype student3 = StudentPrototype.CreateInstance();
                   student1.Id = 234;
                   student1.Name = "CodeMan";
                   student1.Class.ClassId = 2;
                   student1.Class.ClassName = "架构班";
                   //因为string类型的 ="CodeMan" 等同于 new String("CodeMan"); 开辟新的空间,不影响之前的-----实际上string是不可修改的----

                   student2.Id = 345;
                   student2.Name = "左耳听风";
                   student2.Class.ClassId = 3;
                   student2.Class.ClassName = "全栈班";

                   student3.Id = 456;
                   student3.Name = "NULL";
                   student3.Class = new Class()
                   {
                       ClassId = 4,
                       ClassName = "实战班"
                   };//换了个引用
                   student1.Study();
                   student2.Study();
                   student3.Study();
                   //student1的 classid   student2 student3   234   444 或者其他
                   //C#内存分配----334
               }
               {
                   //C#内存分  进程堆(进程唯一)-----线程栈(每个线程一个)
                   //引用类型在堆里,值类型在栈里---变量都在栈里
                   //引用类型对象里面的值类型---student1.Id 堆还是栈?---在堆里
                   //值类型里面的引用类型---Custom.Name 堆还是栈?----在堆里(任何引用类型的值都在堆里)
               }
           }
           catch (Exception ex)
           {
               Console.WriteLine(ex.Message);
           }
           Console.Read();
       }

       private static void Show()
       {
           Console.WriteLine("***************Show**************");
           for (int i = 0; i < 5; i++)
           {
               Student student = new Student()
               {
                   Id = 1121,
                   Name = "馒头哥"
               };
               student.Study();
           }
       }
   }

   public struct Custom
   {
       public string Name;
   }
}

Student.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PrototypePattern
{
   /// <summary>
   /// 普通类
   /// 创建的时候很耗时  耗资源等
   /// </summary>
   public class Student
   {
       public Student()
       {
           Thread.Sleep(2000);
           long lResult = 0;
           for (int i = 0; i < 1000000; i++)
           {
               lResult += i;
           }
           Console.WriteLine("{0}被构造..", this.GetType().Name);
       }

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

       public void Study()
       {
           Console.WriteLine("{0}在学习.net高级班公开课之设计模式特训", this.Name);
       }

   }
}

StudentPrototype.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PrototypePattern
{
   /// <summary>
   /// 普通类
   /// 创建的时候很耗时  耗资源等
   /// </summary>
   public class Student
   {
       public Student()
       {
           Thread.Sleep(2000);
           long lResult = 0;
           for (int i = 0; i < 1000000; i++)
           {
               lResult += i;
           }
           Console.WriteLine("{0}被构造..", this.GetType().Name);
       }

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

       public void Study()
       {
           Console.WriteLine("{0}在学习.net高级班公开课之设计模式特训", this.Name);
       }

   }
}
StudentSingleton.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PrototypePattern
{
   /// <summary>
   /// 单例类
   /// </summary>
   public class StudentSingleton
   {
       /// <summary>
       /// 1 构造函数私有化--避免随意构造
       /// </summary>
       private StudentSingleton()
       {
           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 StudentSingleton _Student = new StudentSingleton()
       {
           Id = 123,
           Name = "ywa"
       };
       /// <summary>
       /// 2 公开的静态方法来提供实例
       /// </summary>
       /// <returns></returns>
       public static StudentSingleton CreateInstance()
       {
           return _Student;
       }


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

       public void Study()
       {
           Console.WriteLine("{0}在学习.net高级班公开课之设计模式特训", this.Name);
       }

   }
}

SerializeHelper.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace PrototypePattern
{
   public class SerializeHelper
   {
       public static string Serializable(object target)
       {
           using (MemoryStream stream = new MemoryStream())
           {
               new BinaryFormatter().Serialize(stream, target);

               return Convert.ToBase64String(stream.ToArray());
           }
       }
       public static T Derializable<T>(string target)
       {
           byte[] targetArray = Convert.FromBase64String(target);

           using (MemoryStream stream = new MemoryStream(targetArray))
           {
               return (T)(new BinaryFormatter().Deserialize(stream));
           }
       }
       public static T DeepClone<T>(T t)
       {
           return Derializable<T>(Serializable(t));
       }
   }
}

最后,想了解更多,可加入CCNetCore社区,橙子带你走上.netcore学习之路。
你可以免费获取到:

  • 设计模式
  • 面试八股文
  • 问题答疑
  • 闲聊茶馆
  • Asp.Netcore图文源码解读
  • 第一代软件架构单体应用相关技术
  • 第二代软件架构分布式应用相关技术
  • 第三代软件架构微服务应用相关技术
  • 第四代软件架构网格服务应用相关技术

站点网址:ccnetcore.com

上一篇:10.22训练赛


下一篇:2021CSP-S题解(待补)