国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn))

這篇具有很好參考價(jià)值的文章主要介紹了【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn))。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

原型模式

介紹

  • 原型模式指用通過(guò)拷貝原型實(shí)例創(chuàng)建新的實(shí)例,新實(shí)例和原型實(shí)例的屬性完全一致
  • 原型模式是一種創(chuàng)建型設(shè)計(jì)模式
  • 工作原理是通過(guò)調(diào)用原型實(shí)例的 clone()方法來(lái)完成克隆,原型實(shí)例需要實(shí)現(xiàn)Cloneable接口,并重寫clone()方法
  • 需要為每個(gè)類開(kāi)發(fā)一個(gè)克隆方法,這對(duì)全新的類來(lái)說(shuō)不難,但對(duì)已有類進(jìn)行改造時(shí),需要修改其源代碼,違背了ocp原則
  • 實(shí)現(xiàn)深拷貝的時(shí)候可能需要比較復(fù)雜的代碼

應(yīng)用場(chǎng)景

在以下情況下,我們就不能根據(jù)new 類名()來(lái)生成實(shí)例,而是克隆現(xiàn)有實(shí)例來(lái)生成新實(shí)例

  • 對(duì)象種類繁多,無(wú)法將它們整合到一個(gè)類中(在軟件設(shè)計(jì)中,有時(shí)候我們需要?jiǎng)?chuàng)建一種類型的對(duì)象,但是該類型下有多個(gè)具體的變體,這些變體之間可能存在大量差異,無(wú)法將這些變體都封裝到一個(gè)類中。這時(shí)候可以使用原型模式,將這些變體作為原型,通過(guò)對(duì)原型進(jìn)行克隆來(lái)得到新的對(duì)象。這樣既避免了創(chuàng)建過(guò)多的分類,又能夠保持對(duì)象的個(gè)性化)
  • 難以通過(guò)new來(lái)創(chuàng)建實(shí)例(有的實(shí)例非常復(fù)雜,想要?jiǎng)?chuàng)建一個(gè)一模一樣的示例非常困難)
  • 想解耦框架與生成的實(shí)例時(shí)(想要讓生成實(shí)例的框架不依賴于具體的類。這時(shí),不能指定類名來(lái)生成實(shí)例,而要事先“注冊(cè)”一個(gè)“原型”實(shí)例,然后通過(guò)復(fù)制該實(shí)例來(lái)生成新的實(shí)例)

類圖

【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn)),設(shè)計(jì)模式,設(shè)計(jì)模式,java,原型模式

  • Prototype : 原型類,聲明一個(gè)克隆自身的接口
  • ConcretePrototype: 具體的原型類,實(shí)現(xiàn)克隆方法
  • Client:調(diào)用原型對(duì)象的克隆方法,讓一個(gè)原型對(duì)象克隆自身來(lái)創(chuàng)建一個(gè)屬性一樣的新對(duì)象

案例分析

克隆羊問(wèn)題

現(xiàn)在有一只羊叫做tom,其屬性為姓名: tom,年齡: 1,顏色:白色,請(qǐng)編寫程序創(chuàng)建和 tom 屬性完全相同的10只羊。

傳統(tǒng)實(shí)現(xiàn)

package com.atguigu.prototype;

public 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;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
    }


}
package com.atguigu.prototype;

public class Client {

   public static void main(String[] args) {
      // TODO Auto-generated method stub
      //傳統(tǒng)的方法
      Sheep sheep = new Sheep("tom", 1, "白色");
      
      Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      //....
      
      System.out.println(sheep);
      System.out.println(sheep2);
      System.out.println(sheep3);
      System.out.println(sheep4);
      System.out.println(sheep5);
      //...
   }

}
分析

【優(yōu)點(diǎn)】

  • 比較好理解,簡(jiǎn)單易操作

【缺點(diǎn)】

  • 在創(chuàng)建新的對(duì)象時(shí),需要獲取原始對(duì)象的屬性,如果創(chuàng)建的對(duì)象比較復(fù)雜時(shí),效率較低,不夠靈活(原型對(duì)象的屬性修改之后,如添加一個(gè)屬性,需要往構(gòu)造方法中添加參數(shù))
  • 總是需要重新初始化對(duì)象,而不能動(dòng)態(tài)地獲得對(duì)象運(yùn)行時(shí)的狀態(tài)

【改進(jìn)】

  • 使用原型模式:在Java中,Obiect類是所有類的根類,Object類提供了一個(gè)clone()方法,該方法可以將一個(gè)Java對(duì)象復(fù)制一份,但是需要實(shí)現(xiàn)clone的Java類必須要實(shí)現(xiàn)一個(gè)接口Cloneable,該接口表示該類能夠復(fù)制且具有復(fù)制的能力

原型模式(淺拷貝)

package com.atguigu.prototype.improve;

/**
 * 繼承Cloneable
 */
public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;
    private String address = "蒙古羊";
    /**
     * 是對(duì)象, 克隆是會(huì)如何處理
     */
    public Sheep friend;

    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";
    }

    /**
     * 克隆該實(shí)例,使用默認(rèn)的clone方法來(lái)完成
     *
     * @return
     */
    @Override
    protected Object clone() {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }

}
package com.atguigu.prototype.improve;

public class Client {

   public static void main(String[] args) {
      System.out.println("原型模式完成對(duì)象的創(chuàng)建");
      Sheep sheep = new Sheep("tom", 1, "白色");
      sheep.friend = new Sheep("jack", 2, "黑色");

      Sheep sheep2 = (Sheep)sheep.clone();
      Sheep sheep3 = (Sheep)sheep.clone();
      Sheep sheep4 = (Sheep)sheep.clone();
      Sheep sheep5 = (Sheep)sheep.clone();

      System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());
      System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode());
      System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode());
      System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode());
   }

}
原型模式完成對(duì)象的創(chuàng)建
sheep2 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep2.friend=1554874502
sheep3 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep3.friend=1554874502
sheep4 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep4.friend=1554874502
sheep5 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep5.friend=1554874502

Process finished with exit code 0

【分析】

  • 根據(jù)輸出,可以看到其他sheep的friend原型對(duì)象的friend是同一個(gè)對(duì)象(因?yàn)閔ashcode一樣),原因:上面的代碼是淺拷貝,淺拷貝并不會(huì)重新復(fù)制一個(gè)引用類型的對(duì)象出來(lái),只是單純將克隆對(duì)象的friend指向原型對(duì)象的friend對(duì)象,這樣的壞處是,如果原型對(duì)象的friend發(fā)生了改變,克隆對(duì)象的friend也會(huì)改變,這樣不能算是真正的克隆

原型模式(深拷貝)

package com.atguigu.prototype.deepclone;

import java.io.Serializable;

public class DeepCloneableTarget implements Serializable, Cloneable {

   private static final long serialVersionUID = 1L;

   private String cloneName;

   private String cloneClass;

   /**
    * 構(gòu)造器
    * @param cloneName
    * @param cloneClass
    */
   public DeepCloneableTarget(String cloneName, String cloneClass) {
      this.cloneName = cloneName;
      this.cloneClass = cloneClass;
   }

   /**
    * 因?yàn)樵擃惖膶傩?,都是String , 因此我們這里使用默認(rèn)的clone完成即可
    * @return
    * @throws CloneNotSupportedException
    */
   @Override
   protected Object clone() throws CloneNotSupportedException {
      return super.clone();
   }
}
package com.atguigu.prototype.deepclone;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DeepProtoType implements Serializable, Cloneable {
    /**
     * 基本數(shù)據(jù)類型
     */
    public String name;
    /**
     * 引用類型
     */
    public DeepCloneableTarget deepCloneableTarget;

    public DeepProtoType() {
        super();
    }

    /**
     * 深拷貝 - 方式 1 使用clone 方法
     *
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //這里完成對(duì)基本數(shù)據(jù)類型(屬性)和String的克隆
        Object deep = super.clone();
        //對(duì)引用類型的屬性,進(jìn)行單獨(dú)處理
        DeepProtoType deepProtoType = (DeepProtoType) deep;
        deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();

        return deepProtoType;
    }

    /**
     * 深拷貝 - 方式2 通過(guò)對(duì)象的序列化實(shí)現(xiàn) (推薦)
     * @return
     */
    public Object deepClone() {

        /// 創(chuàng)建流對(duì)象
        // 字節(jié)輸出流
        ByteArrayOutputStream bos = null;
        // 對(duì)象輸出流
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;

        try {
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            //當(dāng)前這個(gè)對(duì)象以對(duì)象流的方式輸出
            oos.writeObject(this);

            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepProtoType copyObj = (DeepProtoType) ois.readObject();

            return copyObj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            //關(guān)閉流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }
        }

    }

}

【客戶端調(diào)用】

package com.atguigu.prototype.deepclone;

public class Client {

   public static void main(String[] args) throws Exception {
      // TODO Auto-generated method stub
      DeepProtoType p = new DeepProtoType();
      p.name = "宋江";
      p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");

      //方式1 完成深拷貝
      DeepProtoType p2 = (DeepProtoType) p.clone();
      System.out.println("p.name=" + p.name + "; p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
      System.out.println("p2.name=" + p.name + "; p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());

      //方式2 完成深拷貝
      DeepProtoType p3 = (DeepProtoType) p.deepClone();
      System.out.println("p3.name=" + p.name + "; p3.deepCloneableTarget=" + p3.deepCloneableTarget.hashCode());

   }

}

【運(yùn)行】

p.name=宋江; p.deepCloneableTarget=1554874502
p2.name=宋江; p2.deepCloneableTarget=1846274136
p3.name=宋江; p3.deepCloneableTarget=932172204

Process finished with exit code 0

【分析】
可以看到三個(gè)對(duì)象的deepCloneableTarget的hashCode不同,因此克隆成功

字符串修飾問(wèn)題

【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn)),設(shè)計(jì)模式,設(shè)計(jì)模式,java,原型模式

【框架】

package framework;

import java.lang.Cloneable;

public interface Product extends Cloneable {
    /**
     * 實(shí)例使用
     * @param s
     */
    public abstract void use(String s);

    /**
     * 實(shí)例復(fù)制
     * @return
     */
    public abstract Product createClone();
}
package framework;

import java.util.*;

public class Manager {
    /**
     * 存儲(chǔ)實(shí)例名及實(shí)例
     */
    private HashMap showcase = new HashMap();

    /**
     * 注冊(cè)示例
     * @param name
     * @param proto
     */
    public void register(String name, Product proto) {
        showcase.put(name, proto);
    }

    /**
     * 根據(jù)實(shí)例名稱使用實(shí)例
     * @param protoname
     * @return
     */
    public Product create(String protoname) {
        Product p = (Product) showcase.get(protoname);
        return p.createClone();
    }
}

【實(shí)現(xiàn)類】

import framework.*;

/**
 * use 方法的作用是將字符串用雙引號(hào)括起來(lái)顯示,并在字符串下面加上下劃線。例如,當(dāng) ulchar 保存的字符為'~' 方法接收到的字符串為Hello時(shí),顯示結(jié)果如下
 *
 * "Hellor"
 *  ~~~~~~
 */
public class UnderlinePen implements Product {
    private char ulchar;

    public UnderlinePen(char ulchar) {
        this.ulchar = ulchar;
    }

    public void use(String s) {
        int length = s.getBytes().length;
        System.out.println("\"" + s + "\"");
        System.out.print(" ");
        for (int i = 0; i < length; i++) {
            System.out.print(ulchar);
        }
        System.out.println("");
    }

    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}
import framework.*;

/**
 * decochar字段中保存的是像裝飾方框那樣的環(huán)繞著字符串的字符。use方法會(huì)使用decochar字段中保存的字符把要顯示的字符串框起來(lái)。
 * 例如,當(dāng)decochar 中保存的字符為'*',use方法接收到的字符串為 Hello 的時(shí)候,顯示結(jié)果如下
 * <p>
 * *******
 * *Hello*
 * *******
 */
public class MessageBox implements Product {
    private char decochar;

    public MessageBox(char decochar) {
        this.decochar = decochar;
    }

    public void use(String s) {
        int length = s.getBytes().length;
        for (int i = 0; i < length + 4; i++) {
            System.out.print(decochar);
        }
        System.out.println("");
        System.out.println(decochar + " " + s + " " + decochar);
        for (int i = 0; i < length + 4; i++) {
            System.out.print(decochar);
        }
        System.out.println("");
    }

    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

【主類】

import framework.*;

public class Main {
    public static void main(String[] args) {
        // 準(zhǔn)備
        Manager manager = new Manager();
        UnderlinePen upen = new UnderlinePen('~');
        MessageBox mbox = new MessageBox('*');
        MessageBox sbox = new MessageBox('/');
        manager.register("strong message", upen);
        manager.register("warning box", mbox);
        manager.register("slash box", sbox);

        // 生成
        Product p1 = manager.create("strong message");
        p1.use("Hello, world.");
        System.out.println();
        Product p2 = manager.create("warning box");
        p2.use("Hello, world.");
        System.out.println();
        Product p3 = manager.create("slash box");
        p3.use("Hello, world.");
    }
}
"Hello, world."
 ~~~~~~~~~~~~~

*****************
* Hello, world. *
*****************

/
/ Hello, world. /
/

Process finished with exit code 0

分析

對(duì)象種類繁多,無(wú)法將它們整合到一個(gè)類中時(shí)

在示例程序中,一共出現(xiàn)了如下3種樣式。

  • 使用’~'為字符串添加下劃線
  • 使用’*'為字符串添加邊框
  • 使用’/'為字符串添加邊框

本例比較簡(jiǎn)單,只生成了3種樣式,不過(guò)無(wú)論多少種樣式都可以生成。但是如果將每種樣式都編寫為一個(gè)類,類的數(shù)量將會(huì)非常龐大,源代碼的管理也會(huì)變得非常困難。

想解耦框架與生成的實(shí)例時(shí)

在示例程序中,我們將復(fù)制(clone)實(shí)例的部分封裝在framework包中了

在Manager類的create方法中,我們并沒(méi)有使用類名,而是根據(jù)"strong message"和"slash box"等字符串(即實(shí)例名稱)來(lái)生成相應(yīng)的實(shí)例。與Java語(yǔ)言自帶的生成實(shí)例的newSomething()方式相比,這種方式具有更好的通用性,且將框架從類名的束縛中解脫出來(lái)了

登場(chǎng)角色

【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn)),設(shè)計(jì)模式,設(shè)計(jì)模式,java,原型模式

  • Prototype(原型):定義用于復(fù)制現(xiàn)有實(shí)例來(lái)生成新實(shí)例的方法,如上面的Product
  • ConcretePrototype(具體的原型):負(fù)責(zé)實(shí)現(xiàn)復(fù)制現(xiàn)有實(shí)例并生成新實(shí)例的方法,如上面的MessageBox和UnderlinePen
  • Client(使用者):負(fù)責(zé)使用復(fù)制實(shí)例的方法生成新的實(shí)例,如上面的Manager

Spring源碼分析

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">


 <!-- 這里我們的 scope="prototype" 即 原型模式來(lái)創(chuàng)建 -->
 <bean id="id01" class="com.atguigu.spring.bean.Monster" 
   scope="prototype"/>
   
</beans>

scope=“prototype”:使用原型模式

package com.atguigu.spring.bean;

/**
 * 注釋
 * @author Administrator
 *
 */
public class Monster {

   private Integer id = 10 ;
   private String nickname = "牛魔王";
   private String skill = "芭蕉扇";
   public Monster() {
      
      System.out.println("monster 創(chuàng)建..");
   }
   public Monster(Integer id, String nickname, String skill) {
      //System.out.println("Integer id, String nickname, String skill被調(diào)用");
      this.id = id;
      this.nickname = nickname;
      this.skill = skill;
   }
   
   public Monster( String nickname, String skill,Integer id) {
      
      this.id = id;
      this.nickname = nickname;
      this.skill = skill;
   }
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   public String getNickname() {
      return nickname;
   }
   public void setNickname(String nickname) {
      this.nickname = nickname;
   }
   public String getSkill() {
      return skill;
   }
   public void setSkill(String skill) {
      this.skill = skill;
   }
   @Override
   public String toString() {
      return "Monster [id=" + id + ", nickname=" + nickname + ", skill="
            + skill + "]";
   }
   
}
package com.atguigu.spring.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ProtoType {

   public static void main(String[] args) {
      // TODO Auto-generated method stub
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
      // 獲取monster[通過(guò)id獲取monster]
      Object bean = applicationContext.getBean("id01");
      System.out.println("bean" + bean); // 輸出 "牛魔王" .....
      
      Object bean2 = applicationContext.getBean("id01");
      System.out.println("bean2" + bean2); //輸出 "牛魔王" .....
      System.out.println(bean == bean2); // false,并不是同一個(gè)對(duì)象,只是屬性相同

   }

}

【運(yùn)行】

monster 創(chuàng)建..
beanMonster [id=10, nickname=牛魔王, skill=芭蕉扇]
monster 創(chuàng)建..
bean2Monster [id=10, nickname=牛魔王, skill=芭蕉扇]
false

Process finished with exit code 0

【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn)),設(shè)計(jì)模式,設(shè)計(jì)模式,java,原型模式

淺拷貝和深拷貝

淺拷貝

  • 對(duì)于數(shù)據(jù)類型是基本數(shù)據(jù)類型的成員變量,淺拷貝會(huì)直接進(jìn)行值傳遞,也就是將該屬性值復(fù)制一份給新的對(duì)象
  • 對(duì)于數(shù)據(jù)類型是引用數(shù)據(jù)類型的成員變量,比如說(shuō)成員變量是某個(gè)數(shù)組、某個(gè)類的對(duì)象等,那么淺拷貝會(huì)進(jìn)行引用傳遞,也就是只是將該成員變量的引用值 (內(nèi)存地址)復(fù)制一份給新的對(duì)象。因?yàn)閷?shí)際上兩個(gè)對(duì)象的該成員變量都指同一個(gè)實(shí)例。在這種情況下,在一個(gè)對(duì)象中修改該成員變量會(huì)影響到另一個(gè)對(duì)象的該成員變量值
  • sheep = (Sheep) super.clone()這種方式就是淺拷貝

深拷貝

  • 復(fù)制對(duì)象的所有基本數(shù)據(jù)類型的成員變量值
  • 為所有引用數(shù)據(jù)類型的成員變量申請(qǐng)存儲(chǔ)空間,并復(fù)制每個(gè)引用數(shù)據(jù)類型成員變量所引用的對(duì)象

【實(shí)現(xiàn)方式】

  • 重寫clone方法來(lái)實(shí)現(xiàn)深拷貝(缺點(diǎn):麻煩,每個(gè)子對(duì)象都需要調(diào)用克隆方法重新賦值)
  • 通過(guò)對(duì)象序列化實(shí)現(xiàn)深拷貝(缺點(diǎn):速度慢,如果調(diào)用拷貝的次數(shù)多,不要使用這種方式)

深拷貝工具類

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;


public class DeepCloneUtil {
   
   public static Object deepClone(Object srcObject){
      ByteArrayOutputStream bos = null;
      ObjectOutputStream oos = null;
      ByteArrayInputStream bis = null;
      ObjectInputStream ois = null;
      Object result = null;
      try {
         bos = new ByteArrayOutputStream();
         oos = new ObjectOutputStream(bos);
         oos.writeObject(srcObject);
         bis = new ByteArrayInputStream(bos.toByteArray());
         ois = new ObjectInputStream(bis);
         result = ois.readObject();
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         try {
            bos.close();
            oos.close();
            bis.close();
            ois.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      return result;
   }

}

使用方式

A a = new A();
A a1 = (A)DeepCloneUtil.deepClone(a);

clone方法與Clonable接口

  • Object中定義了clone()方法,如果類實(shí)現(xiàn)了Cloneable接口,就可以調(diào)用clone()來(lái)進(jìn)行實(shí)例復(fù)制;否則調(diào)用就會(huì)報(bào)CloneNotSupportedException異常
  • Cloneable接口中并沒(méi)有聲明任何方法。它只是被用來(lái)標(biāo)記“可以使用clone方法進(jìn)行復(fù)制”的,稱為標(biāo)記接口(marker interface)
  • clone 方法只會(huì)進(jìn)行復(fù)制,并不會(huì)調(diào)用被復(fù)制實(shí)例的構(gòu)造函數(shù)。此外,對(duì)于在生成實(shí)例時(shí)需要進(jìn)行特殊的初始化處理的類,需要自已去實(shí)現(xiàn) clone 方法,在其內(nèi)部進(jìn)行這些初始化處理

【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn)),設(shè)計(jì)模式,設(shè)計(jì)模式,java,原型模式文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-604746.html

文章說(shuō)明

  • 本文章為本人學(xué)習(xí)尚硅谷的學(xué)習(xí)筆記,文章中大部分內(nèi)容來(lái)源于尚硅谷視頻(點(diǎn)擊學(xué)習(xí)尚硅谷相關(guān)課程),也有部分內(nèi)容來(lái)自于自己的思考,發(fā)布文章是想幫助其他學(xué)習(xí)的人更方便地整理自己的筆記或者直接通過(guò)文章學(xué)習(xí)相關(guān)知識(shí),如有侵權(quán)請(qǐng)聯(lián)系刪除,最后對(duì)尚硅谷的優(yōu)質(zhì)課程表示感謝。
  • 本人還同步閱讀《圖解設(shè)計(jì)模式》書(shū)籍(圖解設(shè)計(jì)模式/(日)結(jié)城浩著;楊文軒譯–北京:人民郵電出版社,2017.1),進(jìn)而綜合兩者的內(nèi)容,讓知識(shí)點(diǎn)更加全面

到了這里,關(guān)于【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——原型模式Prototype(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【設(shè)計(jì)模式--原型模式(Prototype Pattern)

    【設(shè)計(jì)模式--原型模式(Prototype Pattern)

    原型模式(Prototype Pattern)是一種創(chuàng)建型設(shè)計(jì)模式,它的主要目的是通過(guò)復(fù)制現(xiàn)有對(duì)象來(lái)創(chuàng)建新的對(duì)象,而無(wú)需顯式地使用構(gòu)造函數(shù)或工廠方法。這種模式允許我們創(chuàng)建一個(gè)可定制的原型對(duì)象,然后通過(guò)復(fù)制它來(lái)創(chuàng)建新的對(duì)象,從而避免了重復(fù)構(gòu)建相似的對(duì)象。 在原型模式中

    2024年02月11日
    瀏覽(22)
  • 設(shè)計(jì)模式六:原型模式(Prototype Pattern)

    原型模式是一種創(chuàng)建對(duì)象的設(shè)計(jì)模式。它允許我們通過(guò)復(fù)制一個(gè)現(xiàn)有對(duì)象來(lái)創(chuàng)建新的對(duì)象,而無(wú)需知道其具體實(shí)現(xiàn)細(xì)節(jié)。在使用原型模式時(shí),我們首先創(chuàng)建一個(gè)原始對(duì)象,然后根據(jù)需要復(fù)制該對(duì)象,以獲得新創(chuàng)建的對(duì)象。 原型模式的主要思想是基于對(duì)象的復(fù)制。通過(guò)使用原型

    2024年02月14日
    瀏覽(24)
  • 創(chuàng)建型設(shè)計(jì)模式:5、原型模式(Prototype Pattern)

    目錄 1、原型模式的含義 2、C++實(shí)現(xiàn)原型模式的簡(jiǎn)單實(shí)例 1、原型模式的含義 通過(guò)復(fù)制現(xiàn)有對(duì)象來(lái)創(chuàng)建新對(duì)象,而無(wú)需依賴于顯式的構(gòu)造函數(shù)或工廠方法,同時(shí)又能保證性能。 The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is det

    2024年02月13日
    瀏覽(21)
  • 設(shè)計(jì)模式之原型模式Prototype的C++實(shí)現(xiàn)

    設(shè)計(jì)模式之原型模式Prototype的C++實(shí)現(xiàn)

    1、原型模式提出 在軟件功能設(shè)計(jì)中,經(jīng)常面臨著“某些結(jié)構(gòu)復(fù)雜的對(duì)象”的創(chuàng)建工作,且創(chuàng)建的對(duì)象想擁有其他對(duì)象在某一刻的狀態(tài),則可以使用原型模型。原型模型是通過(guò)拷貝構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象,并且該對(duì)象擁有其他對(duì)象在某一刻的狀態(tài)。 2、需求描述 設(shè)計(jì)產(chǎn)品A,B,這

    2024年02月12日
    瀏覽(21)
  • 《Java極簡(jiǎn)設(shè)計(jì)模式》第05章:原型模式(Prototype)

    《Java極簡(jiǎn)設(shè)計(jì)模式》第05章:原型模式(Prototype)

    作者:冰河 星球:http://m6z.cn/6aeFbs 博客:https://binghe.gitcode.host 文章匯總:https://binghe.gitcode.host/md/all/all.html 源碼地址:https://github.com/binghe001/java-simple-design-patterns/tree/master/java-simple-design-prototype 沉淀,成長(zhǎng),突破,幫助他人,成就自我。 本章難度:★★☆☆☆ 本章重點(diǎn):用

    2024年02月11日
    瀏覽(31)
  • 《golang設(shè)計(jì)模式》第一部分·創(chuàng)建型模式-02-原型模式(Prototype)

    《golang設(shè)計(jì)模式》第一部分·創(chuàng)建型模式-02-原型模式(Prototype)

    用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象 Prototype(抽象原型類):它是聲明克隆方法的接口,或所有具體原型類的公共父類 它可以是抽象類也可以是接口,甚至還可以是具體實(shí)現(xiàn)類。 ConcretePrototype(具體原型類):它實(shí)現(xiàn)在抽象原型類中聲明的

    2024年02月14日
    瀏覽(26)
  • 【23種設(shè)計(jì)模式】原型模式(五)

    【23種設(shè)計(jì)模式】原型模式(五)

    在軟件系統(tǒng)中,當(dāng)創(chuàng)建一個(gè)類的實(shí)例的過(guò)程很昂貴或很復(fù)雜,并且我們需要?jiǎng)?chuàng)建多個(gè)這樣類的實(shí)例時(shí),如果我們用new操作符去創(chuàng)建這樣的類實(shí)例,這就會(huì)增加創(chuàng)建類的復(fù)雜度和創(chuàng)建過(guò)程與客戶代碼復(fù)雜的耦合度。如果采用工廠模式來(lái)創(chuàng)建這樣的實(shí)例對(duì)象的話,隨著產(chǎn)品類的不

    2024年02月10日
    瀏覽(20)
  • 用Rust實(shí)現(xiàn)23種設(shè)計(jì)模式之原型模式

    在 Rust 中,原型模式可以通過(guò)實(shí)現(xiàn) Clone trait 來(lái)實(shí)現(xiàn)。原型模式是一種創(chuàng)建型設(shè)計(jì)模式,它允許通過(guò)復(fù)制現(xiàn)有對(duì)象來(lái)創(chuàng)建新對(duì)象,而無(wú)需顯式地使用構(gòu)造函數(shù)。下面是一個(gè)使用 Rust 實(shí)現(xiàn)原型模式的示例,帶有詳細(xì)的代碼注釋和說(shuō)明: 在上述示例中,我們首先定義了一個(gè)原型對(duì)

    2024年02月14日
    瀏覽(16)
  • 原型模式 Prototype Pattern 《游戲編程模式》學(xué)習(xí)筆記

    原型模式 Prototype Pattern 《游戲編程模式》學(xué)習(xí)筆記

    用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。 假設(shè)我現(xiàn)在要做一款游戲,這個(gè)游戲里有許多不同種類的怪物,鬼魂,惡魔和巫師。這些怪物通過(guò)“生產(chǎn)者”進(jìn)入這片區(qū)域,每種敵人有不同的生產(chǎn)者。 假設(shè)每種怪物都有不同的類,同時(shí)他們都繼承怪

    2024年02月12日
    瀏覽(24)
  • 【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——狀態(tài)模式State(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn))

    【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——狀態(tài)模式State(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn))

    請(qǐng)編寫程序完成APP抽獎(jiǎng)活動(dòng)具體要求如下: 假如每參加一次這個(gè)活動(dòng)要扣除用戶50積分,中獎(jiǎng)概率是10% 獎(jiǎng)品數(shù)量固定,抽完就不能抽獎(jiǎng) 活動(dòng)有四個(gè)狀態(tài): 可以抽獎(jiǎng)、不能抽獎(jiǎng)、發(fā)放獎(jiǎng)品和獎(jiǎng)品領(lǐng)完,活動(dòng)的四個(gè)狀態(tài)轉(zhuǎn)換關(guān)系圖如下 一開(kāi)始的狀態(tài)為“不能抽獎(jiǎng)”,當(dāng)扣除50積分

    2024年02月12日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包