在C#中,原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过克隆现有对象来创建新对象,而无需依赖于显式的构造函数。原型模式通过复制现有对象的属性和状态,创建一个新对象,并在需要创建对象时返回这个克隆的副本。
原型模式的核心是使用原型接口或基类来定义克隆方法,并让具体类实现该方法来实现克隆功能。在C#中,原型模式的实现方式可以使用对象的MemberwiseClone()
方法或序列化和反序列化来实现。
原型模式的意义在于对象的复用,减小对象构建对资源的开销
1.单例原型
单例模式:保证整个进程中,该对象只有一个实例
public class StudentSingleton
{
public int Id { get; set; }
public string Name { get; set; }
/// <summary>
/// 构造函数私有化
/// </summary>
private StudentSingleton()
{
Console.WriteLine("{0}被构造..", this.GetType().Name);
}
/// <summary>
/// 静态字段
/// </summary>
private static StudentSingleton _Student = new StudentSingleton()
{
Id = 001,
Name = "小明"
};
/// <summary>
/// 开放的静态方法获取实例
/// </summary>
/// <returns></returns>
public static StudentSingleton CreateInstance()
{
return _Student;
}
public void Study()
{
Console.WriteLine("{0}正在学习", this.Name);
}
}
internal class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
StudentSingleton student = StudentSingleton.CreateInstance();
student.Study();
}
//输出结果
//StudentSingleton被构造..
//小明正在学习
//小明正在学习
//小明正在学习
}
}
扩展:C#内存分配机制
C#中的内存分配面向对象,对于值类型(如int、float)和引用类型(如string、类)的内存分配方式有所不同
int
的内存分配:int
是值类型,它的值直接存储在栈上。当声明一个 int
变量时,分配的内存空间大致等于一个 int
的大小(通常为4字节)。
string
的内存分配:string
是引用类型,它的实例存储在托管堆(Managed Heap)上。当使用 new
关键字创建一个 string
对象时,会在堆上分配一块内存空间来存储字符串的值。
{
Console.WriteLine("***************Singleton**************");
StudentSingleton student1 = StudentSingleton.CreateInstance();
StudentSingleton student2 = StudentSingleton.CreateInstance();
student1.Id = 002;
student1.Name = "小红";
student2.Id = 003;
student2.Name = "小黄";
Console.WriteLine(student1.Id);
Console.WriteLine(student1.Name);
Console.WriteLine(student2.Id);
Console.WriteLine(student2.Name);
//输出结果
//3
//小黄
//3
//小黄
}
单例模式整个进程只有一个实例,在C#内存分配机制中student1与student2属于引用类型,指向堆的同一块区域。所以后面的会覆盖前面的。
2.拷贝原型
MemberwiseClone()
方法:内存拷贝,不走构造函数,直接内存copy,所以没有性能损失;
public class Classroom
{
public int ClassroomId { get; set; }
public string ClassroomName { get; set; }
}
public class StudentPrototype
{
public int Id { get; set; }
public string Name { get; set; }
public Classroom classroom { get; set; }
/// <summary>
/// 构造函数私有化
/// </summary>
private StudentPrototype()
{
Console.WriteLine("{0}被构造..", this.GetType().Name);
}
/// <summary>
/// 静态字段
/// </summary>
private static StudentPrototype _Student = new StudentPrototype()
{
Id = 001,
Name = "小明",
classroom = new Classroom()
{
ClassroomId = 1,
ClassroomName = "小学"
}
};
/// <summary>
/// 开放的静态方法获取实例
/// </summary>
/// <returns></returns>
public static StudentPrototype CreateInstance()
{
StudentPrototype student = (StudentPrototype)_Student.MemberwiseClone();
return student;
}
public void Study()
{
Console.WriteLine("{0}{1}正在{2}号{3}学习", this.Name, this.Id, this.classroom.ClassroomId, this.classroom.ClassroomName);
}
}
{
Console.WriteLine("***************Prototype**************");
StudentPrototype student1 = StudentPrototype.CreateInstance();
StudentPrototype student2 = StudentPrototype.CreateInstance();
StudentPrototype student3 = StudentPrototype.CreateInstance();
student1.Id = 002;
student1.Name = "小红";
student1.classroom.ClassroomId = 2;
student1.classroom.ClassroomName = "初中";
//因为string类型的 ="CodeMan" 等同于 new String("CodeMan"); 开辟新的空间,不影响之前的-----实际上string是不可修改的----
student2.Id = 003;
student2.Name = "小黄";
student2.classroom.ClassroomId = 3;
student2.classroom.ClassroomName = "高中";
student3.Id = 004;
student3.Name = "小蓝";
student3.classroom = new Classroom()
{
ClassroomId = 4,
ClassroomName = "大学"
};
student1.Study();
student2.Study();
student3.Study();
//输出结果
//StudentPrototype被构造..
//小红2正在3号高中学习
//小黄3正在3号高中学习
//小蓝4正在4号大学学习
}
student1与student2的classroom属性属于引用类型,MemberwiseClone()
方法属于浅拷贝,只拷贝classroom属性的引用地址。
StudentPrototype中的Name属性也属于引用类型(string),但student1.Name = "小红"等同于student1.Name = new String("小红"),这是String类型的特性,每次重新赋值只会重新开辟一块新的空间。
student3的classroom属性把引用的地址重新赋值,完成了深拷贝——不仅拷贝引用,还得拷贝引用类型的值。
标签:Name,student2,student1,PrototypePattern,StudentPrototype,模式,原型,StudentSingleton, From: https://www.cnblogs.com/ZHIZRL/p/17617550.html