zoukankan      html  css  js  c++  java
  • 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         }
    View Code

    主函数:

     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         }
    View Code

    题目延伸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     }
    View Code

    实现:

    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();
                }
            }
    View Code

    主函数:

     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         }
    View Code

    题目延伸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         }
    View Code

    所以这就涉及到了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         }
    View Code

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

  • 相关阅读:
    计算字符串中al_num,spance_num,digit_num,other_num的个数
    for与if、else的使用
    len字符串的长度
    Measuring Signal Similarities
    离散信号MATLAB频谱分析程序
    给新人程序员的八点建议 转载
    翻译网站
    jquery常用选择器
    java处理数据库的CRUD
    JDBC连接数据库工具类
  • 原文地址:https://www.cnblogs.com/Aries-rong/p/7607573.html
Copyright © 2011-2022 走看看