<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          好似你,餅印咁:原型模式、淺拷貝與深拷貝

          共 4397字,需瀏覽 9分鐘

           ·

          2021-01-12 01:35

          0x01:原型模式簡介

          用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。大概意思就是:允許一個對象再創(chuàng)建另外一個可定制的對象,根本無需知道對象創(chuàng)建的細(xì)節(jié)。其工作原理是通過將一個原型對象傳給那個要發(fā)動創(chuàng)建的對象,這個要發(fā)動創(chuàng)建的對象通過請求原型對象拷貝它們自己來實施創(chuàng)建。其UML類圖如下:

          主要角色如下:

          • Prototype:為原型類,聲明一個克隆自身的接口;

          • ConcretePrototype:為具體實現(xiàn)類,實現(xiàn)一個克隆自身的操作;

          Client(客戶端)只需讓一個原型克隆自身,就可以創(chuàng)建一個新的對象。

          原型模式主要用于對象的拷貝,其核心是就是類圖中的原型類Prototype,其一般是一個java抽象類或是一個接口,定義了具體原型類所需要的實現(xiàn)的方法。


          0x02:原型模式的實現(xiàn)

          原型類Prototype

          public?abstract?class?Prototype?{

          ????private?String?name;

          ????private?String?sex;

          ????public?Prototype()?{

          ????}

          ????public?Prototype(String?name,?String?sex)?{
          ????????super();
          ????????this.name?=?name;
          ????????this.sex?=?sex;
          ????}

          ????public?String?getName()?{
          ????????return?name;
          ????}

          ????public?void?setName(String?name)?{
          ????????this.name?=?name;
          ????}

          ????public?String?getSex()?{
          ????????return?sex;
          ????}

          ????public?void?setSex(String?sex)?{
          ????????this.sex?=?sex;
          ????}

          ????//聲明一個實現(xiàn)克隆自身的方法
          ????public?abstract?Prototype?clone();

          }

          具體實現(xiàn)類ConcretePrototype

          public?class?ConcretePrototype?extends?Prototype{

          ????public?ConcretePrototype(String?name,?String?sex)?{
          ????????super(name,?sex);
          ????}

          ????@Override
          ????public?ConcretePrototype?clone()?{
          ????????return?new?ConcretePrototype(this.getName(),?this.getSex());
          ????}

          }

          原型模式測試代碼

          public?class?Client?{

          ????public?static?void?main(String[]?args)?{
          ????????ConcretePrototype?p?=?new?ConcretePrototype("Hello",?"gril");
          ????????ConcretePrototype?c?=?(ConcretePrototype)?p.clone();
          ????????System.out.println(c.getName()?+?",?"?+?c.getSex());
          ????}

          }


          0x03:JDK中淺拷貝、深拷貝與原型模型

          Java賦值是復(fù)制對象引用,如果想要得到一個對象的副本,使用賦值操作是無法達到目的的

          普通pojo對象Person

          public?class?Person?{

          ????private?String?name;

          ????private?int?age;

          ?????//省略getter ?setter
          }

          測試代碼

          public?static?void?main(String[]?args)?{
          ??????Person?p1?=?new?Person();
          ??????p1.setAge(31);
          ??????p1.setName("java樂園");

          ??????Person?p2?=?p1;
          ??????System.out.println(p1==p2);//?true
          }

          如果創(chuàng)建一個對象的新的副本,也就是說他們的初始狀態(tài)完全一樣,但以后可以改變各自的狀態(tài),而互不影響,就需要用到Java中對象的復(fù)制,如原生的clone()方法。如何進行對象克隆呢?

          Object對象有個clone()方法,實現(xiàn)了對象中各個屬性的復(fù)制,但它的可見范圍是protected的,所以實體類使用克隆的前提是:

          • 實現(xiàn)Cloneable接口,這是一個標(biāo)記接口,自身沒有任何方法;?

          • 覆蓋clone()方法,可見性提升為public;

          public?class?Person?implements?Cloneable{

          ????private?String?name;

          ????private?int?age;

          ?????//省略getter ?setter

          ????@Override
          ????protected?Object?clone()?throws?CloneNotSupportedException?{
          ????????return?super.clone();
          ????}

          }

          測試代碼

          public?static?void?main(String[]?args)?throws?Exception{
          ????????Person?p1=new?Person();
          ??????????p1.setAge(31);
          ??????????p1.setName("java樂園");

          ??????????Person?p2=(Person)?p1.clone();
          ??????????System.out.println(p1?==?p2);//false
          ??????????p2.setName("架構(gòu)師知音");
          ??????????System.out.println("p1?=?"?+?p1.getName()?+?",?"?+?p1.getAge());?//?p1?=?java樂園,?31
          ??????????System.out.println("p2?=?"?+?p2.getName()?+?",?"?+?p2.getAge());?//p2?=?架構(gòu)師知音,?31

          ????}

          該測試用例只有兩個基本類型的成員變量,測試目的達到。好像沒有任何問題?為Person增加一個地址的引用類型成員變量Address

          public?class?Address?{

          ????private?String?city;

          ????private?String?street;

          ????//省略getter setter

          }

          Person增加Address成員對象

          public?class?Person?implements?Cloneable{

          ????private?String?name;

          ????private?int?age;

          ????private?Address?address;
          //省略 getter setter

          ????@Override
          ????protected?Object?clone()?throws?CloneNotSupportedException?{
          ????????return?super.clone();
          ????}


          }

          測試代碼

          public?static?void?main(String[]?args)?throws?Exception{
          ??????????Address?address=new?Address();
          ??????????address.setStreet("天庭88號");
          ??????????address.setCity("魔都");

          ??????????Person?p1=new?Person();
          ??????????p1.setAge(31);
          ??????????p1.setName("java樂園");
          ??????????p1.setAddress(address);

          ??????????Person?p2=(Person)?p1.clone();
          ??????????System.out.println(p1?==?p2);?//false

          ??????????p2.getAddress().setCity("廣東");
          ??????????System.out.println("p1="?+?p1.getAddress().getCity());
          ??????????System.out.println("p2="+??p2.getAddress().getCity());
          ????}

          遇到了麻煩,只修改了p2的城市,兩個地址城市都變成了“廣東”。這個實例是淺拷貝和深拷貝的典型用例

          • 淺拷貝:被復(fù)制對象的所有值屬性都含有與原來對象的相同,而所有的對象引用屬性仍然指向原來的對象。

          • 深拷貝:在淺拷貝的基礎(chǔ)上,所有引用其他對象的變量也進行了clone,并指向被復(fù)制過的新對象。

          也就是說,一個默認(rèn)的clone()方法實現(xiàn)機制,仍然是賦值。

          如果一個被復(fù)制的屬性都是基本類型,那么只需要實現(xiàn)當(dāng)前類的cloneable機制就可以了,此為淺拷貝;如果被復(fù)制對象的屬性包含其他實體類對象引用,那么這些實體類對象都需要實現(xiàn)Cloneable接口并覆蓋clone()方法。對Address做以下修改:

          public?class?Address?implements?Cloneable?{
          ????private?String?city;

          ????private?String?street;

          ????//省略?getter??setter

          ????@Override
          ????protected?Object?clone()?throws?CloneNotSupportedException?{
          ????????return?super.clone();
          ????}
          }

          通過以上案例可以看出通過Cloneable接口并覆蓋Object類的clone()方法就很方便的實現(xiàn)了原型模式。

          參考:https://www.cnblogs.com/xuanxufeng/p/6558330.html

          喜歡,在看


          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一道无码在线视 | 免费看日本黄色电影 | 午夜操穴 | 亚洲综合婷婷深深 | 91 无码 国产 |