1.原型模式介绍

  在软件系统开发中,有时候会遇到这样的情况:我们需要用到多个相同实例,最简单直接的方法是通过多次调用new方法来创建相同的实例。如下:

Person person=new Person(){Name="jack",Age=};
Person person2=new Person(){Name="jack",Age=};
Person person3=new Person(){Name="jack",Age=};

  但是有一个问题,如果我用要使用的实例创建起来十分耗费资源,或者创建起来步骤比较繁琐,上边的代码缺点就暴露出来了:耗费资源,每次创建实例都要重复繁琐的创建过程。原始模式可以很好地解决这个问题,使用原型模式我们不需要每次都new一个新的实例,而是通过拷贝原有的对象来完成创建,这样我们就不需要在内存中创建多个对象,也不需要重复复杂的创建过程了。下边以克隆人为例解释原型模式的用法,代码非常简单。

人类原型类,提供了一个克隆抽象方法:

   /// <summary>
/// 人类原型抽象类
/// </summary>
public abstract class PersonPrototype
{
public abstract object clone();
}

人类继承原型类,表示人类可以被克隆,每个人都有名字,年龄和住址:

   /// <summary>
/// Person
/// </summary>
public class Person: PersonPrototype
{
public string Name { get; set; }
public int Age { get; set; }
public Address Address { get; set; } public override object clone()
{
//MemberwiseClone方法实现浅拷贝
return this.MemberwiseClone();
}
} /// <summary>
/// 住址
/// </summary>
public class Address
{
public string Province { get; set; }
public string City { get; set; }
}

客户端代码:

        static void Main(string[] args)
{
//创建一个person实例
Person person1 = new Person()
{
Name = "jack",
Age = ,
Address = new Address{Province = "山东",City = "青岛"}
};
//一个克隆人,通过clone方法替代了new方法
Person clonePerson = (Person)person1.clone(); Console.WriteLine($"person1的name:{person1.Name},年龄:{person1.Age}," +
$"省份:{person1.Address.Province},城市:{person1.Address.City}");
Console.WriteLine($"克隆人的name:{clonePerson.Name},年龄:{clonePerson.Age}," +
$"省份:{clonePerson.Address.Province},城市:{clonePerson.Address.City}");
Console.ReadKey();
}

运行结果如下:

我们可以看到,通过clone方法成功获取了一个相同的person实例。

这里需要注意一点:通过object.MemberWiseClone()获取一个对象的实例属于浅拷贝,对实例的简单类型属性进行全值拷贝(包含string类型),对复杂类型属性只拷贝了引用。客户端代码如下

       static void Main(string[] args)
{
//创建一个person实例
Person person1 = new Person()
{
Name = "jack",
Age = ,
Address = new Address{Province = "山东", City = "青岛"}
};
//一个克隆人
Person clonePerson = (Person)person1.clone();
clonePerson.Name = "tom";
clonePerson.Age = ;
clonePerson.Address.Province = "浙江";
clonePerson.Address.City = "杭州"; Console.WriteLine($"person1的name:{person1.Name},年龄:{person1.Age}," +
$"省份:{person1.Address.Province},城市:{person1.Address.City}");
Console.WriteLine($"克隆人的name:{clonePerson.Name},年龄:{clonePerson.Age}," +
$"省份:{clonePerson.Address.Province},城市:{clonePerson.Address.City}");
Console.ReadKey();
}
}

运行结果:对于复杂类型Address,修改clonePerson的省份和城市,person1的Address也修改了。而修改clonePerson的名字,person1的名字没有变。

修改clonePerson的名字,person1的名字没有变,这一点是MemberwishClone方法和直接赋值的区别,我们修改客户端代码,将

       static void Main(string[] args)
{
//创建一个person实例
Person person1 = new Person()
{
Name = "jack",
Age = ,
Address = new Address{Province = "山东",City = "青岛"}
};
//这里使用直接赋值,而不是clone
Person clonePerson = person1;
clonePerson.Name = "tom";
clonePerson.Age = ;
clonePerson.Address.Province = "浙江";
clonePerson.Address.City = "杭州"; Console.WriteLine($"person1的name:{person1.Name},年龄:{person1.Age}," +
$"省份:{person1.Address.Province},城市:{person1.Address.City}");
Console.WriteLine($"克隆人的name:{clonePerson.Name},年龄:{clonePerson.Age}," +
$"省份:{clonePerson.Address.Province},城市:{clonePerson.Address.City}");
Console.ReadKey();
}

运行结果:直接赋值修改字符串类型的属性(name)原始实例也会修改

2.小结

上边例子的类图

原型模式的优点:

  1.隐藏了创建实例的繁琐过程,只需通过Clone方法就可以获取实例对象

  2.使用浅拷贝替代new,减少资源消耗

原型模式的缺点:

  1.需要添加一个Clone方法,C#中一般使用MemberwishClone方法来获取实例的浅拷贝副本。

补充:如果想实现深拷贝常用的有两种方法:①将原始实例序列化,然后反序列化赋值给副本对象;②浅拷贝+递归的方式,类似于遍历文件夹,对所有的复杂属性、复杂属性内部的复杂属性都进行浅拷贝。

C#设计模式(6)——原型模式的更多相关文章

  1. 设计模式_11_原型模式(prototype)深拷贝、浅拷贝

    设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...

  2. C#设计模式(6)——原型模式(Prototype Pattern)

    一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在 ...

  3. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  4. C#设计模式之六原型模式(Prototype)【创建型】

    一.引言 在开始今天的文章之前先说明一点,欢迎大家来指正.很多人说原型设计模式会节省机器内存,他们说是拷贝出来的对象,这些对象其实都是原型的复制,不会使用内存.我认为这是不对的,因为拷贝出来的每一个对 ...

  5. C#设计模式之五原型模式(Prototype Pattern)【创建型】

    一.引言 在开始今天的文章之前先说明一点,欢迎大家来指正.很多人说原型设计模式会节省机器内存,他们说是拷贝出来的对象,这些对象其实都是原型的复制,不会使用内存.我认为这是不对的,因为拷贝出来的每一个对 ...

  6. C#设计模式(6)——原型模式(Prototype Pattern)(转)

    一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在 ...

  7. C#设计模式(6)——原型模式(Prototype Pattern) C# 深浅复制 MemberwiseClone

    C#设计模式(6)——原型模式(Prototype Pattern)   一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创 ...

  8. JAVA 设计模式之原型模式

    目录 JAVA 设计模式之原型模式 简介 Java实现 1.浅拷贝 2.深拷贝 优缺点说明 1.优点 2.缺点 JAVA 设计模式之原型模式 简介 原型模式是六种创建型设计模式之一,主要应用于创建相同 ...

  9. C# Json反序列化 C# 实现表单的自动化测试<通过程序控制一个网页> 验证码处理类:UnCodebase.cs + BauDuAi 读取验证码的值(并非好的解决方案) 大话设计模式:原型模式 C# 深浅复制 MemberwiseClone

    C# Json反序列化   Json反序列化有两种方式[本人],一种是生成实体的,方便处理大量数据,复杂度稍高,一种是用匿名类写,方便读取数据,较为简单. 使用了Newtonsoft.Json,可以自 ...

  10. GOF23设计模式之原型模式

    GOF23设计模式之原型模式 1)通过 new 产生一个对象需要飞船繁琐的数据准备或访问权限,则可以使用原型模式. 2)就算 java 中的克隆技术,以某个对象为原型,复制出新的对象.显然,新的对象具 ...

随机推荐

  1. Elasticsearch 关键字与SQL关键字对比总结

    由于Elasticsearch和MongoDB/Redis/Memcache一样,是非关系型数据库.而平常使用的MySql,Oracle,SQLServer 等为关系型数据库,二者有着本质的区别,Es ...

  2. UOJ272 [清华集训2016] 石家庄的工人阶级队伍比较坚强 【分治乘法】

    题目分析: 首先不难注意到式子就是异或卷积,所以考虑用分治乘法推出优化方法.我们把一个整体$f$拆成$f-,f\pm,f+$,然后另一个拆成$g-,g\pm,g+$.这样做的好处是能更清楚的分析问题. ...

  3. Server socket

    用法都一样 区别:  self.request   TCP  self.requsst 代表具体的链接 UDP  self.requst 代表一个小元组(元组里面: 第一个元素 客户端发来的数据 ,第 ...

  4. [HDU2065] "红色病毒"问题

    传送门:>Here< 题意:现在有一长度为N的字符串,满足一下条件: (1) 字符串仅由A,B,C,D四个字母组成; (2) A出现偶数次(也可以不出现); (3) C出现偶数次(也可以不 ...

  5. Codeforces300 F. A Heap of Heaps

    Codeforces题号:#300F 出处: Codeforces 主要算法:树状数组/线段树 难度:4.6 思路分析: 在没看到数据范围之前真是喜出望外,直到发现O(n^2)会被卡…… 其实也不是特 ...

  6. PIGS POJ - 1149(水最大流)

    题意: 有M个猪圈,每个猪圈里初始时有若干头猪.一开始所有猪圈都是关闭的.依次来了N个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪.每个顾客分别都有他能够买的数量的上限.每个顾客走后,他打开 ...

  7. luogu3233 世界树 (虚树)

    反正肯定要建虚树,考虑建完之后怎么做 先随便dp一下算出来距离某点最近的询问点mi[x](因为有的虚树上的点它不是询问点嘛) 那我们对于某条链x到fa[x]上的非虚树上的点(包括他们的非虚树上的孩子) ...

  8. 项目部署之nginx实现PC端和移动端自动跳转

    假设PC端域名为 www.abc.com     移动端域名为m.abc.com PC端nginx配置文件server中加入如下代码: if ($http_host !~ "^www.abc ...

  9. jquery 事件的绑定,触发和解绑

    js和jquery绑定的区别? HTML或原生js是单一对应绑定的,绑多了只留最后一个.jQuery是追加绑定的,绑多少执行多少.这个在每一本jQuery的书中都是首先提到的事情. jquery绑定与 ...

  10. CF132E Bits of merry old England

    解:略一思索:网络流啊!(别问我是怎么想到的......) 发现跟志愿者招募有点像.于是把图建一下,在下面开一条通道,但是每个点又都要经过,这时我们就无脑上下界一波. 通道向点连边,有费用.每个点向它 ...