C#学习笔记-原型模式

题目:编写基本的简历。

实现:

创建基本的Resume类,然后主函数通过实例化Resume来写简历即可。

Resume类:

 1 class Resume
 2         {
 3             private string name;
 4             private string sex;
 5             private string age;
 6             private string timeArea;
 7             private string company;
 8
 9             public Resume(string name)
10             {
11                 this.name = name;
12             }
13
14             //设置个人信息
15             public void  SetPersonalInfo(string sex,string age)
16             {
17                 this.age = age;
18                 this.sex = sex;
19             }
20
21             public void SetWorkExperience(string timeArea,string company)
22             {
23                 this.timeArea = timeArea;
24                 this.company = company;
25             }
26
27             public void Show()
28             {
29                 Console.WriteLine("{0}  {1}  {2} ", name, sex, age);
30                 Console.WriteLine("工作经历:{0}  {1} ", timeArea, company);
31             }
32         }

主函数:

 1 static void Main(string[] args)
 2         {
 3             //每写一份简历就实例化一次Resume,写一百分相同的简历也要实例化一百次
 4             //且如果写错了一个词就得修改同样次数的简历
 5             Resume a = new Resume("Taylor");
 6             a.SetPersonalInfo("女", "28");
 7             a.SetWorkExperience("1999-2008", "QWE");
 8             a.Show();
 9
10             Resume b = new Resume("Selena");
11             b.SetPersonalInfo("女", "28");
12             b.SetWorkExperience("1999-2008", "MNB");
13             b.Show();
14
15             //Console.Read();
16
17             //这是传引用,而不是传值,这样如同在c1和b1的纸张上写着:简历在a1处,并没有实际的内容
18             Resume a1 = new Resume("Taylor");
19             a1.SetPersonalInfo("女", "28");
20             a1.SetWorkExperience("1999-2008", "QWE");
21             a1.Show();
22
23             Resume b1 = a1;
24             Resume c1 = a1;
25
26             b1.Show();
27             c1.Show();
28
29             Console.Read();
30         }

题目延伸1:如果我们现在批量打印简历,如果用上面的方法就得每写一份简历都得实例化一次,且如果简历的某种信息输入错误,那么我们就得修改同样次数的简历,这就使工作量变得巨大了。

解析:

这时我们就需要引进原型模式(Prototype)

原型模式(Prototype),用原型实例指定创建对象的种类,并且 通过拷贝这些原型创建新的对象。

原型模式的范例:(这个例子是书上看来的,敲完了,看完了,还是理解的不是特别清楚,我的理解还是比较适合实例一点,这个真的看得无力......)

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             ConcretePrototypel p1 = new ConcretePrototypel("I");
 6             ConcretePrototypel c1 = (ConcretePrototypel)p1.Clone();
 7             Console.WriteLine("Cloned: {0}", c1.Id);
 8
 9             ConcretePrototypel2 p2 = new ConcretePrototypel2("II");
10             ConcretePrototypel2 c2 = (ConcretePrototypel2)p2.Clone();
11             Console.WriteLine("Cloned: {0}", c2.Id);
12
13             // Wait for user
14             Console.Read();
15
16         }
17     }
18
19     //原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
20     abstract class Prototype
21     {
22         private string id;
23
24         public Prototype(string id)
25         {
26             this.id = id;
27         }
28
29         public string Id
30         {
31             get
32             {
33                 return id;
34             }
35         }
36
37         public abstract Prototype Clone();
38     }
39
40
41     class ConcretePrototypel:Prototype
42     {
43         public ConcretePrototypel(string id):base(id)
44         {
45         }
46
47         public override Prototype Clone()
48         {
49             //创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的
50             //非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。
51             //如果字段是引用类型,则复制引用但不复制引用的对象。
52             //因此,原始对象及副本引用同一对象。
53             return (Prototype)this.MemberwiseClone();
54         }
55     }
56
57
58     class ConcretePrototypel2 : Prototype
59     {
60         public ConcretePrototypel2(string id) : base(id)
61         {
62         }
63
64         public override Prototype Clone()
65         {
66             //
67             // 摘要:
68             //     创建当前 System.Object 的浅表副本。
69             //
70             // 返回结果:
71             //     当前 System.Object 的浅表副本。
72             return (Prototype)this.MemberwiseClone();
73         }
74     }

实现:

Resume类:

class Resume
        {
            private string name;
            private string sex;
            private string age;
            private string timeArea;
            private string company;

            public  Resume(string name)
            {
                this.name = name;
            }

            public void SetPersonalInfo(string sex,string age)
            {
                this.sex = sex;
                this.age = age;
            }

            public void SetWorkExperience(string timeArea,string company)
            {
                this.timeArea = timeArea;
                this.company = company;
            }

            public void Display()
            {
                Console.WriteLine("{0}  {1}   {2}", name, sex, age);
                Console.WriteLine("工作经历:{0}   {1}", timeArea, company);
            }

            public object Clone()
            {
                /**
                 * MemberwiseClone()方法:
                 * 如果字段是值类型,则对该字段执行逐位复制,
                 * 如果字段是引用类型,则复制引用但不复制引用的对象
                 * 因此,原始对象及其复本引用同一对象
                 *
                 * 换句话就是,
                 * 如果Resume中有对象引用,那么引用的对象数据是不会被克隆过来的
                 */
                return (object)this.MemberwiseClone();
            }
        }

主函数:

 1 static void Main(string[] args)
 2         {
 3             /**一般在初始化的信息不发生变化的情况下,
 4              * 克隆是最好的办法
 5              * 这既隐藏了对象创建的细节,又对性能是大大的提高
 6              *
 7              * 不用重新初始化对象,而是动态地获取对象运行时的状态
 8              */
 9             Resume a = new Resume("taylor");
10             a.SetPersonalInfo("女", "28");
11             a.SetWorkExperience("1999-2008", "YUT");
12
13             Resume b = (Resume)a.Clone();
14             b.SetWorkExperience("1998-2006", "RTE");
15
16             Resume c = (Resume)a.Clone();
17             c.SetPersonalInfo("男", "30");
18
19             a.Display();
20             b.Display();
21             c.Display();
22
23             Console.Read();
24         }

题目延伸2:如果在简历中设置一个“工作经历”类,其中包括“时间区间”和“公司名称”等属性,简历直接调用这个对象即可。

解析:

如果按照正常的方式书写就会发现,中途如果修改了工作经历的信息,那么所有的简历工作经历都变成了最后一次修改的信息。

对于工作经历里的参数而言,他们属于静态的参数值,故此他们的最后显示会根据最后的输入值。

 1 static void Main(string[] args)
 2         {
 3             Resume a = new Resume("Taylor");
 4             a.SetPersonalInfo("28", "女");
 5             a.SetWorkExperience("1999-2008", "UIO");
 6
 7             Resume b = (Resume)a.Clone();
 8             b.SetWorkExperience("1990-2000", "QWE");
 9             b.SetPersonalInfo("24", "男");
10
11             Resume c = (Resume)a.Clone();
12             c.SetPersonalInfo("30", "男");
13             c.SetWorkExperience("1000-2000", "QWE");
14             //最后c的将work.WorkDate设置为了"1000-2000",work.Company设置为了"QWE"
15             //故此b的工作经历显示也如同c一般了,a也同理
16             //==>“浅复制”
17
18             a.Display();
19             b.Display();
20             c.Display();
21
22             Console.Read();
23         }
24
25         class Resume:ICloneable
26         {
27             private string name;
28             private string sex;
29             private string age;
30
31             private WorkExperience work;
32
33
34             public Resume(string name)
35             {
36                 this.name = name;
37                 work = new WorkExperience();//实例化
38             }
39
40             public void SetPersonalInfo(string age,string sex)
41             {
42                 this.age = age;
43                 this.sex = sex;
44             }
45
46             public void SetWorkExperience(string timeArea,string company)
47             {
48                 work.WorkDate = timeArea;
49                 work.Company = company;
50
51             }
52
53             public void Display()
54             {
55                 Console.WriteLine("{0} {1} {2}", name, sex, age);
56                 Console.WriteLine("工作经历:{0} {1}", work.WorkDate, work.Company);
57             }
58
59             public object Clone()
60             {
61                 return (object)this.MemberwiseClone();
62             }
63         }
64
65         class WorkExperience
66         {
67             private string workDate;
68
69             public string WorkDate
70             {
71                 get
72                 {
73                     return workDate;
74                 }
75
76                 set
77                 {
78                     workDate = value;
79                 }
80             }
81
82             private string company;
83
84             public string Company
85             {
86                 get
87                 {
88                     return company;
89                 }
90
91                 set
92                 {
93                     company = value;
94                 }
95             }
96         }

所以这就涉及到了MemberwiseClone()方法,“浅复制”和“深复制”问题了。

MemberwiseClone():如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同意对象。

=>换句话就是,简历中所包含的对象引用,其引用的对象数据是不会被克隆过来的。

MemberwiseClone()就是“浅复制”:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

“深复制”:把引用对象的变量指向复制过的新对象,而不是原来的被引用的对象。

实现:

 1 class Resume:ICloneable
 2         {
 3             private string name;
 4             private string age;
 5             private string sex;
 6
 7             private WorkExperience work;
 8             public Resume(string name)
 9             {
10                 this.name = name;
11                 work = new WorkExperience();
12             }
13
14             /// <summary>
15             /// 私有函数
16             /// 将工作经历克隆过来
17             /// </summary>
18             /// <param name="work"></param>
19             private Resume(WorkExperience work)
20             {
21                 this.work = (WorkExperience)work.Clone();
22             }
23
24             public void SetPersonalInfo(string age,string sex)
25             {
26                 this.age = age;
27                 this.sex = sex;
28             }
29
30             public void SetWorkExperience(string workDate,string company)
31             {
32                 work.Company = company;
33                 work.WorkDate = workDate;
34             }
35
36             public void Display()
37             {
38                 Console.WriteLine("{0} {1} {2}", name, sex, age);
39                 Console.WriteLine("工作经历:{0} {1}", work.WorkDate, work.Company);
40             }
41
42
43             public object Clone()
44             {
45                 //调用私有的构造方法,让“工作经历”克隆完成
46                 //然后再给这个“简历”对象的相关字段赋值
47                 //最终返回一个深复制的简历对象
48                 Resume obj = new Resume(this.work);
49                 obj.name = this.name;
50                 obj.sex = this.sex;
51                 obj.age = this.age;
52
53                 return obj;
54             }
55         }
56
57         class WorkExperience : ICloneable
58         {
59             private string workDate;
60             private string company;
61
62             public string WorkDate
63             {
64                 get
65                 {
66                     return workDate;
67                 }
68
69                 set
70                 {
71                     workDate = value;
72                 }
73             }
74
75             public string Company
76             {
77                 get
78                 {
79                     return company;
80                 }
81
82                 set
83                 {
84                     company = value;
85                 }
86             }
87
88             public object Clone()
89             {
90                 return (object)this.MemberwiseClone();
91             }
92         }

注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。

时间: 2024-10-05 22:33:24

C#学习笔记-原型模式的相关文章

设计模式学习笔记——原型模式

1.特点:在初始化信息不发生变化时考虑. 2.概念:通过复制一个已经存在的实例来创建一个新的实例.被复制的实例被称为原型,这个原型是可定制的. 3.类图: 4.程序实现: /// <summary> /// 实现了ICloneable接口的简历类 /// </summary> public class Resume:ICloneable { public Resume() { mWorkExperience = new WorkExperience(); } private str

设计模式学习笔记--原型模式

1 using System; 2 3 namespace Prototype 4 { 5 /// <summary> 6 /// 作者:bzyzhang 7 /// 时间:2016/5/24 19:46:36 8 /// 博客地址:http://www.cnblogs.com/bzyzhang/ 9 /// WorkExperience说明:本代码版权归bzyzhang所有,使用时必须带上bzyzhang博客地址 10 /// </summary> 11 public class

LVS学习笔记--DR模式部署

一.部署环境: 服务器版本:CentOS6.5(Finnal) 网络拓扑: 二.需求分析:调度服务器与网页服务器均在同一网段局域网环境,用户提交的请求会经过调度器的分配指定到网页服务器,同时保证服务高可用性(任意一台网站服务器宕机后调度器会剔除它直至服务器恢复至正常:主调度器宕机后从调度器会接管它直至其恢复正常.). 三.相关配置: 部署调度器LVS服务脚本: #!/bin/sh mkdir tools cd tools/ # yum install lrzsz # rz # ls wget h

《Head First 设计模式》学习笔记——模板方法模式

模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.这就是模板方法模式的用意. 设计模式 模板方法模式:在一个方法中定义一个算法的框架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结果的情况下,重新定义算法中的某些步骤. 模板就是一个方法,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现.这样可以确

设计模式学习05—原型模式

一.动机与定义 之前学习原型模式一直以为原型模式目的是为了方便的创建相同或相似对象,用复制对象的方式替换new的方式,还研究了深克隆和浅克隆.最近仔细看了GOF的设计模式,发现原型模式的本意并不仅仅是复制对象这么简单. 复制对象确实是一方面,当我们需要大量相似,甚至相同对象的时候,除了一个个的new之外,还可以根据一个原型,直接复制出更多的对象.但是如果把原型模式认为只是复制对象这么简单就错了. 创建型模式主要讲如何创建对象,通常包含何时创建,谁来创建,怎么创建等.GOF书里面写的意图是,用原型

《Head First 设计模式》学习笔记——单件模式

设计模式 单件模式:确保一个类只有一个实例,并提供一个全局访问点. 要点 单件模式确保程序中一个类最多只有一个实例. 在Java中实现单件模式需要私有的构造器.一个静态方法.一个静态变量. 确定在性能和资源上的限制,然后小心翼翼的选择适当的方案来实现单件,以解决多线程问题. 全局变量缺点 如果将对象赋值给一个全局变量,那么必须在程序一开始就创建好对象.万一对象非常耗费资源,而程序在这次执行过程中并没有使用它,就形成了浪费. 单件模式 public class Singleton { //利用一个

大话设计模式笔记 原型模式

原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节. 基本类型与引用类型的区别于关系在efficient java. http://www.cnblogs.com/linkarl/p/4785329.html 浅复制:对象的引用仍然指向原来的对象 深复制:把引用对象的变量指向复制过的新对象 我认为一般深复制比较常用. package prototype; public

设计模式学习笔记--外观模式

好久没写设计模式的blog了,这次重新回来填坑,先找一个最简单但是却最常用的设计模式来学习,外观模式.其实说是一个设计模式,其实我们在实际的编程中无时无刻不在用外观模式,可以说这个设计模式已经渗透到编程的各个方便,可能我们自己没感觉出来罢了. 一.外观模式的定义 先来看一下外观模式的定义: 外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这一系列子系统更加容易使用. 简单解释一下,所谓外观模式,就是在我们设计系统的时候,将若干个子系统的功

设计模式 笔记 原型模式 prototype

//---------------------------15/04/07---------------------------- //prototype 原型模式--对象创建型模式 /* 1:意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2:动机: 3:适用性: 1>当一个系统应该独立于它的产品创建.构成和表示时 2>当要实例化的类是在运行时刻制定时,例如通过动态装载 3>为了避免创建一个与产品类层次平行的工厂类层次时 4>当一个类的实例只能有几个不同状