1. 程式人生 > 其它 >設計模式之原型設計

設計模式之原型設計

設計模式之原型模式
  1. 問題:現在有一隻羊tom,姓名為:tom,年齡為:1,顏色為:白色,請編寫程式建立和tom羊屬性完全相同的10只羊

    1. 程式碼

      //傳統的解決思路:可以使用類圖展示一下
      class Sheep{
      private String name;
      private int age;
      private String color;
      public Sheep(String name,int age,String color){
      super();
      this.name=name;
      this.age=age;
      this.color=color;
      }
      //編寫setter和getter方法
      //編寫toString()
      }

      //客戶端
      public class Test{
      public static void main(String[] args){
      //傳統方式:
      //優點: 比較好理解,簡單易操作
      //缺點:1.在建立新的物件的時候,總是需要重新獲取原始物件的屬性,如果建立的物件比較複雜的時候,效率較低 2.總是需要重新初始化物件,而不是動態的獲取物件執行時的狀態,不夠靈活
      //改進思路:java中Object類是所有類的根類。Object類提供了一個clone()方法,該方法可以將一個java物件複製一份,但是需要實現clone()方法的java類必須要實現一個介面CloneAble,該介面表示該類可以複製並且具有複製能力-----》原型模式

      Sheep sheep=new Sheep("tom",1,"白色");
      Sheep sheep1= new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
      Sheep sheep2= new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor()); Sheep sheep3= new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
      }


      }
      }

    2. 原型模式

      1. 基本介紹

        1. 原型模式:是指用原型例項指定建立物件的種類,並且通過拷貝這些原型,建立新的物件

        2. 原型模式是一種建立型模式,允許一個物件再建立另一個可定製物件,無需知道如何建立的細節

        3. 工作原理:通過一個原型物件傳給那個要發動建立的物件,這個要發動建立的物件通過請求原型物件拷貝他們自己來實施建立,即物件.clone()

        4. 形象的瞭解:孫悟空拔出猴毛變出其他孫悟空

      2. 程式碼

        .//實現cloneable介面。重寫clone()方法
        class Sheep implements Cloneable{
        private String name;
        private int age;
        private String color;
        public Sheep(String name,int age,String color){
        super();
        this.name=name;
        this.age=age;
        this.color=color;
        }
        //編寫setter和getter方法
        //編寫toString()
        //重寫clone(),克隆該例項,使用預設的克隆方法老完成
        @Override
        protected Object clone(){
        Sheep sheep = null;
        try{
        sheep =(Sheep)super.clone();
        }catch(Exception e){
        System.out.println(e.getMessage());
        }
        return sheep;
        }
        }

        //客戶端
        public class Client{
        public static void main(String[] args){
        Sheep sheep=new Sheep("tom",1,"白色");
        Sheep sheep1=(Sheep)sheep.clone();
        }
        }

      3. 原型模式在Spring框架中的使用

        1. spring中bean的建立就是使用了原型模式,通過.xml中的bean標籤中的scope屬性設定的prototype

      4. 原型模式中淺拷貝和深拷貝介紹

        1. 淺拷貝介紹

          1. 對於資料型別是基本資料型別的成員變數,淺拷貝會直接進行值傳遞,也就是將該屬性值複製一份給新的物件

          2. 對於資料型別是引用資料型別的成員變數,比如說成員變數是某個陣列、某個類的物件等,那麼淺拷貝會進行引用傳遞,也就是隻將該成員變數的引用值(記憶體地址)複製一份給新的物件。因為兩個物件的該成員變數都指向同一個例項。在這種情況下,在一個物件中修改該成員變數會影響到另一個物件的該成員變數值(程式碼證明)

          3. 上面所說的克隆羊就是淺拷貝

          4. 淺拷貝是使用預設的clone()方法來實現的

        2. 深拷貝介紹

          1. 複製物件的所有基本資料型別的成員變數值

          2. 為所有引用資料型別的成員變數申請儲存空間,並複製每個引用資料型別成員變數所引用的物件,知道該物件可達的物件。也就是說,物件進行深拷貝要對整個物件進行拷貝

          3. 深拷貝實現方式

            1. 重寫clone方法來實現深拷貝

            2. 通過物件序列化實現深拷貝

            3. 程式碼實現

              //深拷貝實現,實現序列化介面和克隆介面
              public class DeepCloneTarget implements Serializable,Clobeable{
              private String cloneName;
              private String cloneClass;
              //全參構造
              //重寫clone()方法,因為該類的屬性都是String,因此這裡使用預設的克隆方法
              protected Object clone() throws CloneNotSupportedException{
              return super.clone();
              }
              }

              //深拷貝原型類
              public class DeepProtoType implements Serializable,Conleable{
              //方便期間使用public
              public String name;
              public DeepCloneTarget deepCloneTarget;
              //編寫無參構造
              //實現深拷貝--方式一:clone方法
              @Override
              protected Object clone() throws CloneNotSupportedException{
              Object deep = null;
              //先完成基本資料型別和string型別的克隆
              deep = super.clone();
              //對引用資料型別的屬性進行單獨處理
              DeepProtoType deepProtoType=(DeepProtoType)deep;
              deepProtoType.deepCloneTarget=(DeepCloneTarget)deepCloneTarget.clone();
              return deepProtoType;
              }

              //深拷貝 方式二 通過物件的序列化實現深拷貝(強烈推薦)
              public Object deepClone(){
              //建立流物件
              ByteArrayOutputStream bos = null;
              ObjectOutputStream oos=null;
              ByteArrayInputStream bis= null;
              ObjectInputStream ois= null;
              try{
              //序列化
              bos = new ByteArrayOutputStream();
              oos = new ObjectOutputStream(bos);
              oos.writeObject(this);//把當前物件通過物件流的方式輸出

              //反序列化
              bis =new ByteArrayInputStream(bos.toByteArray());
              ois = new ObjectInputStream(bis);
              DeepProtoType copy=(DeepProtoType) ois.readObject(this);
              return copy;
              }catch(Exception e){
              e.printStackTrace();
              return null;
              }finally{
              //關閉流
              try{
              ois.close();
              bis.close();
              oos.close();
              bos.close();
              }catch(Exception e2){
              System.out.println(e2.getMassage());
              }
              }

              }
              }

              //client
              public class client{
              public static void main(String[] args) throws Exception{
              DeepProtoType p = new DeepProtoType();
              p.name="宋江";
              p.deepCloneTarget = new DeepCloneTarget("小特","王牌君");

              //使用方式一完成深拷貝
              DeepProtoType p1=(DeepProtoType) p.clone();
              System.out.println(p.deepCloneTarget.hashCode()==p1.deepCloneTarget.hashCode());//應該為false

              //方式2實現深拷貝
              DeepProtoType p = new DeepProtoType();
              p.name="宋江";
              p.deepCloneTarget = new DeepCloneTarget("小特","王牌君");
              DeepProtoType p1= (DeepProtoType)p.deepClone();
              System.out.println(p.deepCloneTarget.hashCode()==p1.deepCloneTarget.hashCode());//應該為false
              }
              }

      5. 原型模式的注意事項和細節

        1. 建立型的物件比較複雜的時候,可以利用原型模式簡化物件的建立過程,同時也能夠提高效率

        2. 不用重新初始化物件,而是動態的獲取物件的執行時狀態

        3. 如果原始物件發生變化(增加或者減少屬性)其他可能物件也會發生相應的變化,而不需要修改程式碼

        4. 在實現深拷貝的時候可能需要比較複雜的程式碼

        5. 缺點:需要為每一個類配備一個克隆方法,這對於一個全新的類來說並不難,但是對於已經有的類進行改造時,需要修改其原始碼,違背了ocp原則