zoukankan      html  css  js  c++  java
  • Javascript玩转Prototype(一)——先谈C#原型模式

     在《Javascript玩转继承(二)》中,我使用了原型继承法来实现Javascript的继承,那原型究竟奥秘何在。在这篇文章中,我就主要针对原型来展开讨论。

      抛开Javascript,我们先来看我们熟悉的常规的面向对象语言。在23种设计模式中,大家一定会记得有一种设计模式——原型模式。我们先来看一下结构图:

      (原图引自:http://terrylee.cnblogs.com/archive/2006/01/16/317896.html)

    Javascript玩转Prototype(一)——先谈C#原型模式

      图片看不清楚?请点击这里查看原图(大图)。

      先来复习一下原型模式:看到这个图,大家一定会注意到这个千千万万的Clone()方法,这个就是原型模式的核心。原型模式就是用原型实例来创建对象的种类,然后通过拷贝这些原型来创建新的对象。

      在.NET中,这个模式的实现很容易,我们只需要实现ICloneable接口:

      我还记得在爱情左灯右行里那个Angel说了这样一句话,任何东西到了批量生产的时候,这个质量就得不到保证了。这个是典型的原型模式:批量生产。为什么质量会下降呢?原因就在于他是采用的复制。

      看代码:

    class People:ICloneable
    {
         private string name;
         private int age;
         private List<string> friends = new List<string>();
         public People(string name,int age,params string[] names)
         {     
              this.name=name;
              this.age=age;
              foreach (string s in names)
              {
                   friends.Add(s);
              }
         }
         public string Name
         {
              get{return name;}
              set{name=value;}
         }
         public int Age
         {
              get{return age;}
              set{age=value;}
         }
         public List<string> Friends
         {
              get { return friends; }
              set { friends = value; }
         }
         public object Clone()
         {
              return this.MemberwiseClone();
         }
         public override string ToString()
         {
              string ret = "name:"+name+" age:"+age+" friends: ";
              foreach (string s in friends)
              {
                   ret += s + ",";
              }
              return ret;
         }
    }

    然后我们初始化一个对象:

    People p1 = new People("Windking", 20, "111", "222", "333", "444");

      接下来复制一个对象:

    People p2 = (People)p1.Clone();

      输出一下:

    Console.WriteLine("p1:" + p1.ToString());
    Console.WriteLine("p2:" + p2.ToString());

    Javascript玩转Prototype(一)——先谈C#原型模式

      好,现在来改变:

    p2.Name = "Xuan";
    p2.Age = 22;
    p2.Friends.Add("555");

      再输入:

    Console.WriteLine("p1:" + p1.ToString());
    Console.WriteLine("p2:" + p2.ToString());

    Javascript玩转Prototype(一)——先谈C#原型模式

      我们看到:p2的改变直接作用到了原型p1的数组元素。因为这只是一个浅复制,在复制的时候,对于引用类型只是复制了他的地址,也就是说当两个对象指向内部的同一个引用对象,因此当修改的时候,引用类型的值是牵一发而动全身的。这也就是所谓的"任何东西到了批量生产的时候,这个质量就得不到保证了"。

      可能这时会有人问:String不也是引用类型么?为什么他并没有因为p2的改变而影响的原型呢?关于这个请关注我的下一篇文章:《C#玩转String》。

      那怎么办?可以解决么?可以的。之前是浅复制,我们只需要改成深复制,这就不是批量生产了,其实我个人认为这就不算克隆了,而只是相当于把创建新对象的任务给封装起来 罢了。先看这张图来理解下深复制和浅复制。

      (原图引自:http://www.cnblogs.com/Terrylee/archive/2006/01/06/312493.html)

    Javascript玩转Prototype(一)——先谈C#原型模式

      好,看看深复制的代码:

      其他的代码与上述都一样,不同的只是复制的代码:

    public object Clone()
    {
         List<string> cloneFriends = new List<string>(friends);
         string[] cloneArrayFriends = cloneFriends.ToArray();
                //其实一点都不神秘,不过是把初始化对象封装罢了。
         return new People(this.name, this.age, cloneArrayFriends);
    }

      测试下:

    Javascript玩转Prototype(一)——先谈C#原型模式

      p2的改变没有影响到原型p1。

      好了,本来是要讲Javascript的Prototype的,结果却罗嗦了一页面的原型模式。太多了,我会在下文中来讨论Javascript的Prototype。敬请关注。

    转自:http://tech.ddvip.com/2009-05/1243588153121460_2.html
  • 相关阅读:
    hadoop2 作业执行过程之reduce过程
    hadoop2 作业执行过程之map过程
    hadoop2 作业执行过程之yarn调度执行
    scala的下划线
    tomcat 配置系列1
    Windows Server 2008 __ Windows Server 2008R2
    dell技术中心
    戴尔服务器启动和raid设置(以dell r420为例)
    WinPE安装windows(dell r420)
    Red Hat enterprise linux 5.4 x64 + DELL R420 安装网卡驱动 (broadcom 5270)
  • 原文地址:https://www.cnblogs.com/stalwart/p/2043225.html
Copyright © 2011-2022 走看看