Java描述设计模式(05):原型模式
一、原型模式簡介
1、基礎概念
原型模式屬于對象的創建模式。通過給出一個原型對象來指明所有創建的對象的類型,然后用復制這個原型對象的辦法創建出更多同類型的對象。
2、模式結構
原型模式要求對象實現一個可以“克隆”自身的接口,這樣就可以通過復制一個實例對象本身來創建一個新的實例。這樣一來,通過原型實例創建新的對象,就不再需要關心這個實例本身的類型,只要實現了克隆自身的方法,就可以通過這個方法來獲取新的對象,而無須再去通過new來創建。
3、代碼實現
1)、UML關系圖
Java描述設計模式(05):原型模式
2)、核心角色
這種形式涉及到三個角色:
1)、客戶(Client)角色:客戶類提出創建對象的請求。
2)、抽象原型(Prototype)角色:這是一個抽象角色,通常由一個Java接口或Java抽象類實現。此角色給出所有的具體原型類所需的接口。
3)、具體原型(Concrete Prototype)角色:被復制的對象。此角色需要實現抽象的原型角色所要求的接口。
3)、基于JDK源碼實現
/*** 基于JDK源碼方式實現原型模式*/ public class C01_Property {public static void main(String[] args) {Product product = new Product("機械鍵盤","白色",100.00) ;Product product1 = (Product) product.clone();Product product2 = (Product) product.clone();System.out.println(product1);System.out.println(product2);System.out.println(product1==product2); // false} } class Product implements Cloneable {private String name ;private String color ;private Double price ;public Product(String name, String color, Double price) {this.name = name;this.color = color;this.price = price;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", color='" + color + '\'' +", price=" + price +'}';}@Overrideprotected Object clone() {Product product = null ;try{product = (Product)super.clone() ;} catch (Exception e){e.printStackTrace();}return product ;}// 省略GET和SET方法 }二、Spring框架應用
1、配置文件
<!-- 多例Bean --> <bean id="sheep01" class="com.model.design.spring.node05.property.Sheep" scope="prototype" /> <!-- 單例Bean 默認: scope="singleton" --> <bean id="sheep02" class="com.model.design.spring.node05.property.Sheep"/>2、測試代碼塊
@Test public void test01 (){ApplicationContext context01 = new ClassPathXmlApplicationContext("/spring/spring-property.xml");// 原型模式Sheep sheep1 = (Sheep)context01.getBean("sheep01") ;Sheep sheep2 = (Sheep)context01.getBean("sheep01") ;System.out.println(sheep1==sheep2); // false// 單例模式Sheep sheep3 = (Sheep)context01.getBean("sheep02") ;Sheep sheep4 = (Sheep)context01.getBean("sheep02") ;System.out.println(sheep3==sheep4); // true }3、核心源碼
- 所在類:org.springframework.beans.factory.support.AbstractBeanFactory
- 所在方法:doGetBean
1)、執行流程
if (mbd.isSingleton()) {sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {public Object getObject() throws BeansException {try {return AbstractBeanFactory.this.createBean(beanName, mbd, args);} catch (BeansException var2) {AbstractBeanFactory.this.destroySingleton(beanName);throw var2;}}});bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) {var11 = null;Object prototypeInstance;try {this.beforePrototypeCreation(beanName);prototypeInstance = this.createBean(beanName, mbd, args);} finally {this.afterPrototypeCreation(beanName);}bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }2)、單例多例判斷
所以默認就是單例模式,指定[scope=“prototype”]就是原型模式。
public boolean isSingleton() {return "singleton".equals(this.scope) || "".equals(this.scope); } public boolean isPrototype() {return "prototype".equals(this.scope); }三、深淺拷貝
1、淺拷貝
2、深拷貝
1)、概念描述
除了淺拷貝要拷貝的值外,還負責拷貝引用類型的數據。那些引用其他對象的變量將指向被復制過的新對象,而不再是原有的那些被引用的對象,這種對被引用到的對象的復制叫做間接復制。
2)、源代碼實現
序列化實現深度克隆
對象寫到流里的過程是序列化(Serialization)過程;而把對象從流中讀出來的過程則叫反序列化(Deserialization)過程。應當指出的是,寫到流里的是對象的一個拷貝,而原對象仍然存在于JVM里面。
在Java語言里深度克隆一個對象,常常可以先使對象實現Serializable接口,然后把對象(實際上只是對象的拷貝)寫到一個流里(序列化),再從流里讀回來(反序列化),便可以重建對象。
/*** 深拷貝和淺拷貝對比案例*/ public class C02_DeepClone {public static void main(String[] args) throws Exception {Dog dog = new Dog("Tom") ;Dog dog1 = (Dog)dog.clone() ;Dog dog2 = (Dog)dog.clone() ;// dog1:1639622804;dog2:1639622804System.out.println("dog1:"+dog1.cat.hashCode()+";dog2:"+dog2.cat.hashCode());Dog dog3 = (Dog)dog.deepClone() ;Dog dog4 = (Dog)dog.deepClone() ;// dog3:1937348256;dog4:1641808846System.out.println("dog3:"+dog3.cat.hashCode()+";dog4:"+dog4.cat.hashCode());} }class Cat implements Serializable {public String name ;public Cat (String name){this.name = name ;} } class Dog implements Cloneable,Serializable {public String name ;public Cat cat ;public Dog (String name){this.name = name ;this.cat = new Cat("Kit") ;}@Overrideprotected Object clone() {Dog dog = null ;try{dog = (Dog)super.clone() ;} catch (Exception e){e.printStackTrace();}return dog ;}public Object deepClone() throws IOException, ClassNotFoundException{//將對象寫到流里面:序列化ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);//從流里面讀出對象:反序列化ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return ois.readObject();} }四、優缺點總結
1、優點總結
原型模式允許在運行時動態改變具體的實現類型。原型模式可以在運行期間,由客戶來注冊符合原型接口的實現類型,也可以動態地改變具體的實現類型,看起來接口沒有任何變化,但其實運行的已經是另外一個類實例了。因為克隆一個原型就類似于實例化一個類。
2、缺點總結
原型模式最主要的缺點是每一個類都必須配備一個克隆方法。配備克隆方法需要對類的功能進行通盤考慮,這對于全新的類來說不是很難,而對于已經有的類不一定很容易,特別是當一個類引用不支持序列化的間接對象,或者引用含有循環結構的時候。
五、源代碼地址
GitHub地址:知了一笑 https://github.com/cicadasmile/model-arithmetic-parent 碼云地址:知了一笑 https://gitee.com/cicadasmile/model-arithmetic-parent
總結
以上是生活随笔為你收集整理的Java描述设计模式(05):原型模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文件I/O实践(2) --文件stat
- 下一篇: Java中super与this