C#学习笔记-原型模式
题目:编写基本的简历。
实现:
创建基本的Resume类,然后主函数通过实例化Resume来写简历即可。
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.age = age;
this.sex = sex;
} public void SetWorkExperience(string timeArea,string company)
{
this.timeArea = timeArea;
this.company = company;
} public void Show()
{
Console.WriteLine("{0} {1} {2} ", name, sex, age);
Console.WriteLine("工作经历:{0} {1} ", timeArea, company);
}
}
主函数:
static void Main(string[] args)
{
//每写一份简历就实例化一次Resume,写一百分相同的简历也要实例化一百次
//且如果写错了一个词就得修改同样次数的简历
Resume a = new Resume("Taylor");
a.SetPersonalInfo("女", "");
a.SetWorkExperience("1999-2008", "QWE");
a.Show(); Resume b = new Resume("Selena");
b.SetPersonalInfo("女", "");
b.SetWorkExperience("1999-2008", "MNB");
b.Show(); //Console.Read(); //这是传引用,而不是传值,这样如同在c1和b1的纸张上写着:简历在a1处,并没有实际的内容
Resume a1 = new Resume("Taylor");
a1.SetPersonalInfo("女", "");
a1.SetWorkExperience("1999-2008", "QWE");
a1.Show(); Resume b1 = a1;
Resume c1 = a1; b1.Show();
c1.Show(); Console.Read();
}
题目延伸1:如果我们现在批量打印简历,如果用上面的方法就得每写一份简历都得实例化一次,且如果简历的某种信息输入错误,那么我们就得修改同样次数的简历,这就使工作量变得巨大了。
解析:
这时我们就需要引进原型模式(Prototype)
原型模式(Prototype),用原型实例指定创建对象的种类,并且 通过拷贝这些原型创建新的对象。
原型模式的范例:(这个例子是书上看来的,敲完了,看完了,还是理解的不是特别清楚,我的理解还是比较适合实例一点,这个真的看得无力......)
class Program
{
static void Main(string[] args)
{
ConcretePrototypel p1 = new ConcretePrototypel("I");
ConcretePrototypel c1 = (ConcretePrototypel)p1.Clone();
Console.WriteLine("Cloned: {0}", c1.Id); ConcretePrototypel2 p2 = new ConcretePrototypel2("II");
ConcretePrototypel2 c2 = (ConcretePrototypel2)p2.Clone();
Console.WriteLine("Cloned: {0}", c2.Id); // Wait for user
Console.Read(); }
} //原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
abstract class Prototype
{
private string id; public Prototype(string id)
{
this.id = id;
} public string Id
{
get
{
return id;
}
} public abstract Prototype Clone();
} class ConcretePrototypel:Prototype
{
public ConcretePrototypel(string id):base(id)
{
} public override Prototype Clone()
{
//创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的
//非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。
//如果字段是引用类型,则复制引用但不复制引用的对象。
//因此,原始对象及副本引用同一对象。
return (Prototype)this.MemberwiseClone();
}
} class ConcretePrototypel2 : Prototype
{
public ConcretePrototypel2(string id) : base(id)
{
} public override Prototype Clone()
{
//
// 摘要:
// 创建当前 System.Object 的浅表副本。
//
// 返回结果:
// 当前 System.Object 的浅表副本。
return (Prototype)this.MemberwiseClone();
}
}
实现:
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();
}
}
主函数:
static void Main(string[] args)
{
/**一般在初始化的信息不发生变化的情况下,
* 克隆是最好的办法
* 这既隐藏了对象创建的细节,又对性能是大大的提高
*
* 不用重新初始化对象,而是动态地获取对象运行时的状态
*/
Resume a = new Resume("taylor");
a.SetPersonalInfo("女", "");
a.SetWorkExperience("1999-2008", "YUT"); Resume b = (Resume)a.Clone();
b.SetWorkExperience("1998-2006", "RTE"); Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", ""); a.Display();
b.Display();
c.Display(); Console.Read();
}
题目延伸2:如果在简历中设置一个“工作经历”类,其中包括“时间区间”和“公司名称”等属性,简历直接调用这个对象即可。
解析:
如果按照正常的方式书写就会发现,中途如果修改了工作经历的信息,那么所有的简历工作经历都变成了最后一次修改的信息。
对于工作经历里的参数而言,他们属于静态的参数值,故此他们的最后显示会根据最后的输入值。
static void Main(string[] args)
{
Resume a = new Resume("Taylor");
a.SetPersonalInfo("", "女");
a.SetWorkExperience("1999-2008", "UIO"); Resume b = (Resume)a.Clone();
b.SetWorkExperience("1990-2000", "QWE");
b.SetPersonalInfo("", "男"); Resume c = (Resume)a.Clone();
c.SetPersonalInfo("", "男");
c.SetWorkExperience("1000-2000", "QWE");
//最后c的将work.WorkDate设置为了"1000-2000",work.Company设置为了"QWE"
//故此b的工作经历显示也如同c一般了,a也同理
//==>“浅复制” a.Display();
b.Display();
c.Display(); Console.Read();
} class Resume:ICloneable
{
private string name;
private string sex;
private string age; private WorkExperience work; public Resume(string name)
{
this.name = name;
work = new WorkExperience();//实例化
} public void SetPersonalInfo(string age,string sex)
{
this.age = age;
this.sex = sex;
} public void SetWorkExperience(string timeArea,string company)
{
work.WorkDate = timeArea;
work.Company = company; } public void Display()
{
Console.WriteLine("{0} {1} {2}", name, sex, age);
Console.WriteLine("工作经历:{0} {1}", work.WorkDate, work.Company);
} public object Clone()
{
return (object)this.MemberwiseClone();
}
} class WorkExperience
{
private string workDate; public string WorkDate
{
get
{
return workDate;
} set
{
workDate = value;
}
} private string company; public string Company
{
get
{
return company;
} set
{
company = value;
}
}
}
所以这就涉及到了MemberwiseClone()方法,“浅复制”和“深复制”问题了。
MemberwiseClone():如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同意对象。
=>换句话就是,简历中所包含的对象引用,其引用的对象数据是不会被克隆过来的。
MemberwiseClone()就是“浅复制”:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。
“深复制”:把引用对象的变量指向复制过的新对象,而不是原来的被引用的对象。
实现:
class Resume:ICloneable
{
private string name;
private string age;
private string sex; private WorkExperience work;
public Resume(string name)
{
this.name = name;
work = new WorkExperience();
} /// <summary>
/// 私有函数
/// 将工作经历克隆过来
/// </summary>
/// <param name="work"></param>
private Resume(WorkExperience work)
{
this.work = (WorkExperience)work.Clone();
} public void SetPersonalInfo(string age,string sex)
{
this.age = age;
this.sex = sex;
} public void SetWorkExperience(string workDate,string company)
{
work.Company = company;
work.WorkDate = workDate;
} public void Display()
{
Console.WriteLine("{0} {1} {2}", name, sex, age);
Console.WriteLine("工作经历:{0} {1}", work.WorkDate, work.Company);
} public object Clone()
{
//调用私有的构造方法,让“工作经历”克隆完成
//然后再给这个“简历”对象的相关字段赋值
//最终返回一个深复制的简历对象
Resume obj = new Resume(this.work);
obj.name = this.name;
obj.sex = this.sex;
obj.age = this.age; return obj;
}
} class WorkExperience : ICloneable
{
private string workDate;
private string company; public string WorkDate
{
get
{
return workDate;
} set
{
workDate = value;
}
} public string Company
{
get
{
return company;
} set
{
company = value;
}
} public object Clone()
{
return (object)this.MemberwiseClone();
}
}
注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。
C#学习笔记-原型模式的更多相关文章
- 学习笔记——原型模式Prototype
原型模式,简单说就是具有一个克隆方法,外部可以直接使用此方法得到相应对象的拷贝对象. 比如哆啦A梦的复制镜,一照,就把物品拷贝了一份(虽然是镜子复制是相反的,这里就忽略这个细节了) C++中依靠拷贝构 ...
- 《Head first设计模式》学习笔记 – 迭代器模式
<Head first设计模式>学习笔记 – 迭代器模式 代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了!真是个 ...
- 设计模式学习之原型模式(Prototype,创建型模式)(5)
通过序列化的方式实现深拷贝 [Serializable] public class Person:ICloneable { public string Name { get; set; } publi ...
- 设计模式学习心得<原型模式 Prototype >
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式是实现了一个原型接口,该接口用于创建当 ...
- 设计模式 笔记 原型模式 prototype
//---------------------------15/04/07---------------------------- //prototype 原型模式--对象创建型模式 /* 1:意图: ...
- 设计模式之笔记--原型模式(Prototype)
原型模式(Prototype) 定义 原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 类图 描述 提供一个克隆自身的接口--Clone方法. 应用场景 ...
- jquery学习笔记---插件开发模式和结构
JQuery插件开发http://www.cnblogs.com/damonlan/archive/2012/04/06/2434460.html github教程:https://github.co ...
- 学习笔记——解释器模式Interpreter
解释器模式,其实就是编译原理中的语法解释器,如果用在项目中,可以用于实现动态脚本的解析,也就是说项目可以支持用户脚本扩展. 但实际上,这种运行时解释,效率很慢,如果不是很需要的话,不建议使用. 一种简 ...
- [学习笔记] Dispose模式
Dispose模式是.NET中很基础也很重要的一个模式,今天重新复习一下相关的东西并记录下来. 什么是Dispose模式? 什么时候我们该为一个类型实现Dispose模式 使用Dispose模式时应该 ...
随机推荐
- clang命令理解程序
Xcode 创建一个mac OS command Line Tool程序 步骤打开终端 cd + 工程路径(绝对路径)(注:拖拽main.m文件到终端) input —preprocessor— ...
- FlowPortal-BPM——创建新组织架构、表单、流程
一.创建新组织架构 (1)管理流程→组织管理→组织架构添加需要的组织架构→新建新成员或角色 (2)设置成员信息 二.创建新数据源(如果在已有的数据库中操作,只需要添加需要的表) (1)添加新数据库并添 ...
- Camera Sensor
camera sensor分为YUV sensor和Bayer sensor. YUV Sensor YUV Sensor输出的格式是YUV,图像的处理效果使用sensor内部的ISP,BB端接收到的 ...
- ThreadLocal系列(三)-TransmittableThreadLocal的使用及原理解析
ThreadLocal系列(三)-TransmittableThreadLocal的使用及原理解析 上一篇:ThreadLocal系列(二)-InheritableThreadLocal的使用及原理解 ...
- html个人简历
https://gitee.com/aijiawei3344/codes/g8piyjc3kb7nav4whqd2r79 <!DOCTYPE html> <html> < ...
- SQL1042C running a fenced routine (stored procedure/UDF)
Relation to this link http://www-01.ibm.com/support/docview.wss?uid=swg21399105 2015-01-11-13.38.19. ...
- dubbo接口快速测试技巧
在分布式系统的开发中,用到了dubbo+zookeeper技术,最近遇到一个问题,产品上线后,我负责的模块出了问题,某个bean中某个字段的值一直为null,而这个bean是我调用注册在zookeep ...
- deepin安装php5.6
sudo su -echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu xenial main" | tee -a /etc/a ...
- Java 8学习之Lambda表达式
一.lambda表达式 一个lambda表达式包含三个部分: 一段代码 参数 自由变量的值,这里的自由指的是哪些不是参数并且没有在代码中定义的变量. 示例: public static void re ...
- linux 和 windows 安装composer
在 Linux 和 Mac OS X 中可以运行如下命令: curl -sS https://getcomposer.org/installer | phpmv composer.phar /usr/ ...