C# -- 设计模式 -- PrototypePattern 原型模式

记录《Head First 设计模式》
参考 Graphic Design Patterns网站 与 深入设计模式
目的是检查学习情况,同时方便以后复习。

文章目录

  • 一、间述
    • 1-1 意图
    • 1-2 动机
    • 1-3 结构图
    • 1-4 时序图
  • 二、代码示例:
    • 1-1 浅拷贝与深拷贝代码实现
    • 1-2 浅拷贝与深拷贝区别
  • 三 总结
    • 1-1 模式优缺点
    • 1-2 适合场景
    • 1-3 模式应用
    • 1-4 总结

一、间述

1-1 意图

**原型模式 PrototypePattern:使你能够复制已有的对象,而无需使代码依赖它们所属的类。 又称为单件模式或单态模式。该模式是一种 创建型模式

1-2 动机

1-3 结构图

1-4 时序图

二、代码示例:

1-1 浅拷贝与深拷贝代码实现

代码实现

/// 
/// 原型模式:是一种创建型结构,可以复制当前对象,而不需要依赖
/// 
public class Person
{
     
    public int Age;
    public DateTime BirthDate;
    public string Name;
    public IdInfo IdInfo;

    /// 
    /// 浅拷贝:当前对象被拷贝,但当前对象的字段不会被拷贝(举例Name、IdInfo)。
    /// 
    /// 
    public Person ShallowCopy()
    {
     
        return (Person)this.MemberwiseClone();
    }
    /// 
    /// 深拷贝:对对象实例中字段引用的对象也进行拷贝。
    /// 
    /// 返回一个全新的Persom对象
    public Person DeepCopy()
    {
     
        Person clone = (Person)this.MemberwiseClone();
        //深拷贝重新定义引用类型的字段
        clone.IdInfo = new IdInfo(IdInfo.IdNumber);
        clone.Name = string.Copy(Name);
        return clone;

    }
}
/// 
/// Id信息
/// 
public class IdInfo
{
     
    public int IdNumber;
    public IdInfo(int idNumber)
    {
     
        this.IdNumber = idNumber;
    }
}

测试调用

class Program
{
     
    static void Main(string[] args)
    {
     
        Person p1 = new Person();
		p1.BirthDate = Convert.ToDateTime("1995-01-01");
		p1.Age = DateTime.Now.Year-p1.BirthDate.Year;
		p1.Name = "Prototype";
		p1.IdInfo = new IdInfo(123123);

		// 将P1浅拷贝为P2
		Person p2 = p1.ShallowCopy();
		// 将P1深拷贝为P3
		Person p3 = p1.DeepCopy();

		// 展示P1、P2、P3的值
		Console.WriteLine("展示 p1, p2, p3值:");
		Console.WriteLine("   p1 : ");
		DisplayValues(p1);
		Console.WriteLine("   p2 :");
		DisplayValues(p2);
		Console.WriteLine("   p3:");
		DisplayValues(p3);

		// 改变原型P1的值
		p1.Age = 32;
		p1.BirthDate = Convert.ToDateTime("1900-01-01");
		p1.Name = "Frank";
		p1.IdInfo.IdNumber = 123456;
		Console.WriteLine("P1改变后,展示 p1, p2, p3值");
		Console.WriteLine("   P1: ");
		DisplayValues(p1);
		Console.WriteLine("   p2 :");
		DisplayValues(p2);
		Console.WriteLine("   p3 :");
		DisplayValues(p3);
		
        Console.ReadKey();
    }

执行结果

C# -- 设计模式 -- PrototypePattern 原型模式_第1张图片

其中 Console.ReadKey(); 进行断言,调试–>找到"即时窗口",输入“&P1.IdInfo回车”,查看P1、P2、P3的IdInfo的内存地址是否是同一个。

C# -- 设计模式 -- PrototypePattern 原型模式_第2张图片

1-2 浅拷贝与深拷贝区别

  • 浅拷贝:指当对象的字段值被拷贝时,字段引用的对象不会被拷贝
      当前对象字符串类型字段改变数据,浅拷贝对象的字段会改变值。
      例如:如果一个对象有一个指向字符串的字段,同时我们对该对象做了一个浅拷贝,那么这两个对象将引用同一个字符串。
  • 深拷贝:指当对象的字段值被拷贝时,字段引用的对象会被拷贝
      当前对象字段串类型的字段改变数据,深拷贝对象的字段不会改变值。
      例如:如果一个对象有一个指向字符串的字段,同时我们对该对象进行了深拷贝的话,那么我们将创建一个对象和一个新的字符串,新的对象将引用新的字符串。

  也就是说,执行深拷贝创建的新对象和原来对象不会共享任何东西,改变一个对象对另外一个对象没有任何影响。而执行浅拷贝创建的新对象与原来对象共享成员,改变一个对象,另外一个对象的成员也会改变。

三 总结

1-1 模式优缺点

优点:

  • 提供让客户产生未知类型对象的选项。
  • 可以克隆预生成原型,避免反复运行初始化代码。
  • 在某些环境下,复制对象比创建对象更有用

缺点:

  • 克隆包含循环引用的复杂对象可能会非常麻烦

1-2 适合场景

适用场景:

  • 在一个复杂的类层次中,当系统必须从其中的许多类型中创建对象,可以考虑原型。
  • 如果需要复制一些对象,同时希望复制的对象独立于这些对象所属的具体类,可以使用原型模式。
  • 如果子类的区别仅在于对象的初始化方式,那么你可以使用该模式来减少子类的数量。别人创建这些子类的目的可能是为了创建特定类的对象。

1-3 模式应用

模式应用:

  • 细胞分裂。

1-4 总结

  1. 客户代码在不知道要实例化何种特定类的情况下,可以制造出新的实例。
  2. 通常需要创建一个中心化原型注册表,用于存储常用原型
  3. 原型模式可以通过 clonecopy 等方法识别。
  4. 当创建给定类的实例很昂贵或复杂时,可以使用原型模式。

你可能感兴趣的:(设计模式,设计模式)