C# 设计模式之创建型 —— 原型模式
原型模式原型模式(Prototype Pattern)
·
原型模式
原型模式(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---关注对象的创建
更多推荐


所有评论(0)