中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

南寧網(wǎng)站建設(shè)培訓(xùn)班seoheuni

南寧網(wǎng)站建設(shè)培訓(xùn)班,seoheuni,上海建設(shè)門戶網(wǎng)站,wordpress joomla seo原型模式和享元模式,前者是在創(chuàng)建多個實例時,對創(chuàng)建過程的性能進(jìn)行調(diào)優(yōu);后者是用減少創(chuàng)建實例的方式,來調(diào)優(yōu)系統(tǒng)性能。這么看,你會不會覺得兩個模式有點相互矛盾呢? 其實不然,它們的使用是分場…

原型模式和享元模式,前者是在創(chuàng)建多個實例時,對創(chuàng)建過程的性能進(jìn)行調(diào)優(yōu);后者是用減少創(chuàng)建實例的方式,來調(diào)優(yōu)系統(tǒng)性能。這么看,你會不會覺得兩個模式有點相互矛盾呢?

其實不然,它們的使用是分場景的。在有些場景下,我們需要重復(fù)創(chuàng)建多個實例,例如在循環(huán)體中賦值一個對象,此時我們就可以采用原型模式來優(yōu)化對象的創(chuàng)建過程;而在有些場景下,我們則可以避免重復(fù)創(chuàng)建多個實例,在內(nèi)存中共享對象就好了。

今天我們就來看看這兩種模式的適用場景,了解了這些你就可以更高效地使用它們提升系統(tǒng)性能了。

1、原型模式

我們先來了解下原型模式的實現(xiàn)。原型模式是通過給出一個原型對象來指明所創(chuàng)建的對象的類型,然后使用自身實現(xiàn)的克隆接口來復(fù)制這個原型對象,該模式就是用這種方式來創(chuàng)建出更多同類型的對象。

使用這種方式創(chuàng)建新的對象的話,就無需再通過 new 實例化來創(chuàng)建對象了。這是因為 Object 類的 clone 方法是一個本地方法,它可以直接操作內(nèi)存中的二進(jìn)制流,所以性能相對 new 實例化來說,更佳。

1.1、實現(xiàn)原型模式

我們現(xiàn)在通過一個簡單的例子來實現(xiàn)一個原型模式:

   // 實現(xiàn) Cloneable 接口的原型抽象類 Prototype class Prototype implements Cloneable {// 重寫 clone 方法public Prototype clone(){Prototype prototype = null;try{prototype = (Prototype)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return prototype;}}// 實現(xiàn)原型類class ConcretePrototype extends Prototype{public void show(){System.out.println(" 原型模式實現(xiàn)類 ");}}public class Client {public static void main(String[] args){ConcretePrototype cp = new ConcretePrototype();for(int i=0; i< 10; i++){ConcretePrototype clonecp = (ConcretePrototype)cp.clone();clonecp.show();}}}

要實現(xiàn)一個原型類,需要具備三個條件:

  • 實現(xiàn) Cloneable 接口:Cloneable 接口與序列化接口的作用類似,它只是告訴虛擬機可以安全地在實現(xiàn)了這個接口的類上使用 clone 方法。在 JVM 中,只有實現(xiàn)了 Cloneable 接口的類才可以被拷貝,否則會拋出 CloneNotSupportedException 異常。
  • 重寫 Object 類中的 clone 方法:在 Java 中,所有類的父類都是 Object 類,而 Object 類中有一個 clone 方法,作用是返回對象的一個拷貝。
  • 在重寫的 clone 方法中調(diào)用 super.clone():默認(rèn)情況下,類不具備復(fù)制對象的能力,需要調(diào)用 super.clone() 來實現(xiàn)。

從上面我們可以看出,原型模式的主要特征就是使用 clone 方法復(fù)制一個對象。通常,有些人會誤以為 Object a=new Object();Object b=a; 這種形式就是一種對象復(fù)制的過程,然而這種復(fù)制只是對象引用的復(fù)制,也就是 a 和 b 對象指向了同一個內(nèi)存地址,如果 b 修改了,a 的值也就跟著被修改了。

我們可以通過一個簡單的例子來看看普通的對象復(fù)制問題:

class Student {  private String name;  public String getName() {  return name;  }  public void setName(String name) {  this.name= name;  }  }  
public class Test {  public static void main(String args[]) {  Student stu1 = new Student();  stu1.setName("test1");  Student stu2 = stu1;  stu1.setName("test2");  System.out.println(" 學(xué)生 1:" + stu1.getName());  System.out.println(" 學(xué)生 2:" + stu2.getName());  }  
}

如果是復(fù)制對象,此時打印的日志應(yīng)該為:

學(xué)生 1:test1
學(xué)生 2:test2

然而,實際上是:

學(xué)生 2:test2
學(xué)生 2:test2

通過 clone 方法復(fù)制的對象才是真正的對象復(fù)制,clone 方法賦值的對象完全是一個獨立的對象。剛剛講過了,Object 類的 clone 方法是一個本地方法,它直接操作內(nèi)存中的二進(jìn)制流,特別是復(fù)制大對象時,性能的差別非常明顯。我們可以用 clone 方法再實現(xiàn)一遍以上例子。

// 學(xué)生類實現(xiàn) Cloneable 接口
class Student implements Cloneable{  private String name;  // 姓名public String getName() {  return name;  }  public void setName(String name) {  this.name= name;  } // 重寫 clone 方法public Student clone() { Student student = null; try { student = (Student) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return student; } }  
public class Test {  public static void main(String args[]) {  Student stu1 = new Student();  // 創(chuàng)建學(xué)生 1stu1.setName("test1");  Student stu2 = stu1.clone();  // 通過克隆創(chuàng)建學(xué)生 2stu2.setName("test2");  System.out.println(" 學(xué)生 1:" + stu1.getName());  System.out.println(" 學(xué)生 2:" + stu2.getName());  }  
}

運行結(jié)果:

學(xué)生 1:test1
學(xué)生 2:test2

1.2、深拷貝和淺拷貝

在調(diào)用 super.clone() 方法之后,首先會檢查當(dāng)前對象所屬的類是否支持 clone,也就是看該類是否實現(xiàn)了 Cloneable 接口。

如果支持,則創(chuàng)建當(dāng)前對象所屬類的一個新對象,并對該對象進(jìn)行初始化,使得新對象的成員變量的值與當(dāng)前對象的成員變量的值一模一樣,但對于其它對象的引用以及 List 等類型的成員屬性,則只能復(fù)制這些對象的引用了。所以簡單調(diào)用 super.clone() 這種克隆對象方式,就是一種淺拷貝。

所以,當(dāng)我們在使用 clone() 方法實現(xiàn)對象的克隆時,就需要注意淺拷貝帶來的問題。我們再通過一個例子來看看淺拷貝。

// 定義學(xué)生類
class Student implements Cloneable{  private String name; // 學(xué)生姓名private Teacher teacher; // 定義老師類public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  } public Teacher getTeacher() {  return teacher;  }  public void setName(Teacher teacher) {  this.teacher = teacher;  } // 重寫克隆方法public Student clone() { Student student = null; try { student = (Student) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return student; } }  // 定義老師類
class Teacher implements Cloneable{  private String name;  // 老師姓名public String getName() {  return name;  }  public void setName(String name) {  this.name= name;  } // 重寫克隆方法,堆老師類進(jìn)行克隆public Teacher clone() { Teacher teacher= null; try { teacher= (Teacher) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return student; } }
public class Test {  public static void main(String args[]) {Teacher teacher = new Teacher (); // 定義老師 1teacher.setName(" 劉老師 ");Student stu1 = new Student();  // 定義學(xué)生 1stu1.setName("test1");           stu1.setTeacher(teacher);Student stu2 = stu1.clone(); // 定義學(xué)生 2stu2.setName("test2");  stu2.getTeacher().setName(" 王老師 ");// 修改老師System.out.println(" 學(xué)生 " + stu1.getName + " 的老師是:" + stu1.getTeacher().getName);  System.out.println(" 學(xué)生 " + stu1.getName + " 的老師是:" + stu2.getTeacher().getName);  }  
}

運行結(jié)果:

學(xué)生 test1 的老師是:王老師
學(xué)生 test2 的老師是:王老師

觀察以上運行結(jié)果,我們可以發(fā)現(xiàn):在我們給學(xué)生 2 修改老師的時候,學(xué)生 1 的老師也跟著被修改了。這就是淺拷貝帶來的問題。

我們可以通過深拷貝來解決這種問題,其實深拷貝就是基于淺拷貝來遞歸實現(xiàn)具體的每個對象,代碼如下:

   public Student clone() { Student student = null; try { student = (Student) super.clone(); Teacher teacher = this.teacher.clone();// 克隆 teacher 對象student.setTeacher(teacher);} catch (CloneNotSupportedException e) { e.printStackTrace(); } return student; } 

1.3、適用場景

前面我詳講了原型模式的實現(xiàn)原理,那到底什么時候我們要用它呢?

在一些重復(fù)創(chuàng)建對象的場景下,我們就可以使用原型模式來提高對象的創(chuàng)建性能。例如,我在開頭提到的,循環(huán)體內(nèi)創(chuàng)建對象時,我們就可以考慮用 clone 的方式來實現(xiàn)。

例如:

for(int i=0; i<list.size(); i++){Student stu = new Student(); ...
}

我們可以優(yōu)化為:

Student stu = new Student(); 
for(int i=0; i<list.size(); i++){Student stu1 = (Student)stu.clone();...
}

?除此之外,原型模式在開源框架中的應(yīng)用也非常廣泛。例如 Spring 中,@Service 默認(rèn)都是單例的。用了私有全局變量,若不想影響下次注入或每次上下文獲取 bean,就需要用到原型模式,我們可以通過以下注解來實現(xiàn),@Scope(“prototype”)。

2、享元模式

享元模式是運用共享技術(shù)有效地最大限度地復(fù)用細(xì)粒度對象的一種模式。該模式中,以對象的信息狀態(tài)劃分,可以分為內(nèi)部數(shù)據(jù)和外部數(shù)據(jù)。內(nèi)部數(shù)據(jù)是對象可以共享出來的信息,這些信息不會隨著系統(tǒng)的運行而改變;外部數(shù)據(jù)則是在不同運行時被標(biāo)記了不同的值。

享元模式一般可以分為三個角色,分別為 Flyweight(抽象享元類)、ConcreteFlyweight(具體享元類)和 FlyweightFactory(享元工廠類)。抽象享元類通常是一個接口或抽象類,向外界提供享元對象的內(nèi)部數(shù)據(jù)或外部數(shù)據(jù);具體享元類是指具體實現(xiàn)內(nèi)部數(shù)據(jù)共享的類;享元工廠類則是主要用于創(chuàng)建和管理享元對象的工廠類。

2.1、實現(xiàn)享元模式

我們還是通過一個簡單的例子來實現(xiàn)一個享元模式:

// 抽象享元類
interface Flyweight {// 對外狀態(tài)對象void operation(String name);// 對內(nèi)對象String getType();
}
// 具體享元類
class ConcreteFlyweight implements Flyweight {private String type;public ConcreteFlyweight(String type) {this.type = type;}@Overridepublic void operation(String name) {System.out.printf("[類型 (內(nèi)在狀態(tài))] - [%s] - [名字 (外在狀態(tài))] - [%s]\n", type, name);}@Overridepublic String getType() {return type;}
}
// 享元工廠類
class FlyweightFactory {private static final Map<String, Flyweight> FLYWEIGHT_MAP = new HashMap<>();// 享元池,用來存儲享元對象public static Flyweight getFlyweight(String type) {if (FLYWEIGHT_MAP.containsKey(type)) {// 如果在享元池中存在對象,則直接獲取return FLYWEIGHT_MAP.get(type);} else {// 在響應(yīng)池不存在,則新創(chuàng)建對象,并放入到享元池ConcreteFlyweight flyweight = new ConcreteFlyweight(type);FLYWEIGHT_MAP.put(type, flyweight);return flyweight;}}
}
public class Client {public static void main(String[] args) {Flyweight fw0 = FlyweightFactory.getFlyweight("a");Flyweight fw1 = FlyweightFactory.getFlyweight("b");Flyweight fw2 = FlyweightFactory.getFlyweight("a");Flyweight fw3 = FlyweightFactory.getFlyweight("b");fw1.operation("abc");System.out.printf("[結(jié)果 (對象對比)] - [%s]\n", fw0 == fw2);System.out.printf("[結(jié)果 (內(nèi)在狀態(tài))] - [%s]\n", fw1.getType());}
}

輸出結(jié)果:

[類型 (內(nèi)在狀態(tài))] - [b] - [名字 (外在狀態(tài))] - [abc]
[結(jié)果 (對象對比)] - [true]
[結(jié)果 (內(nèi)在狀態(tài))] - [b]

觀察以上代碼運行結(jié)果,我們可以發(fā)現(xiàn):如果對象已經(jīng)存在于享元池中,則不會再創(chuàng)建該對象了,而是共用享元池中內(nèi)部數(shù)據(jù)一致的對象。這樣就減少了對象的創(chuàng)建,同時也節(jié)省了同樣內(nèi)部數(shù)據(jù)的對象所占用的內(nèi)存空間。

2.2、適用場景

享元模式在實際開發(fā)中的應(yīng)用也非常廣泛。例如 Java 的 String 字符串,在一些字符串常量中,會共享常量池中字符串對象,從而減少重復(fù)創(chuàng)建相同值對象,占用內(nèi)存空間。代碼如下:

 String s1 = "hello";String s2 = "hello";System.out.println(s1==s2);//true

還有,在日常開發(fā)中的應(yīng)用。例如,線程池就是享元模式的一種實現(xiàn);將商品存儲在應(yīng)用服務(wù)的緩存中,那么每當(dāng)用戶獲取商品信息時,則不需要每次都從 redis 緩存或者數(shù)據(jù)庫中獲取商品信息,并在內(nèi)存中重復(fù)創(chuàng)建商品信息了。

3、總結(jié)

通過以上講解,相信你對原型模式和享元模式已經(jīng)有了更清楚的了解了。兩種模式無論是在開源框架,還是在實際開發(fā)中,應(yīng)用都十分廣泛。

在不得已需要重復(fù)創(chuàng)建大量同一對象時,我們可以使用原型模式,通過 clone 方法復(fù)制對象,這種方式比用 new 和序列化創(chuàng)建對象的效率要高;在創(chuàng)建對象時,如果我們可以共用對象的內(nèi)部數(shù)據(jù),那么通過享元模式共享相同的內(nèi)部數(shù)據(jù)的對象,就可以減少對象的創(chuàng)建,實現(xiàn)系統(tǒng)調(diào)優(yōu)。

4、思考題

上一講的單例模式和這一講的享元模式都是為了避免重復(fù)創(chuàng)建對象,你知道這兩者的區(qū)別在哪兒嗎?

http://www.risenshineclean.com/news/49850.html

相關(guān)文章:

  • 包頭網(wǎng)站建設(shè)百度網(wǎng)頁版瀏覽器
  • 網(wǎng)站引量方法關(guān)鍵詞排名關(guān)鍵詞優(yōu)化
  • 網(wǎng)站建設(shè)g廣告主資源哪里找
  • 吉林省長春市長春網(wǎng)站建設(shè)哪家好百度快照查詢
  • 手機萬能瀏覽器汕頭seo不錯
  • 深圳網(wǎng)站建設(shè)(信科網(wǎng)絡(luò))周口網(wǎng)站seo
  • 電商網(wǎng)站建設(shè)源碼做網(wǎng)絡(luò)銷售如何找客戶
  • 瀏覽器被病毒網(wǎng)站綁了怎么做武漢seo收費
  • 常州網(wǎng)站建設(shè)博客網(wǎng)站
  • 上海高端品牌網(wǎng)站制作熱點新聞
  • 石家莊做網(wǎng)站建設(shè)的公司排名微信crm客戶管理系統(tǒng)
  • 建立網(wǎng)站的市場價格競價排名機制
  • 網(wǎng)賭網(wǎng)站怎么做的seo百度關(guān)鍵詞優(yōu)化
  • 手機端做的優(yōu)秀的網(wǎng)站網(wǎng)絡(luò)營銷的基本職能
  • 視覺設(shè)計的網(wǎng)站和app滬深300指數(shù)怎么買
  • phpcms v9農(nóng)業(yè)網(wǎng)站模板產(chǎn)品推廣文案100字
  • 竭誠網(wǎng)絡(luò)網(wǎng)站建設(shè)開發(fā)seo優(yōu)化工作內(nèi)容
  • 桐城58網(wǎng)站在那里做北京百度公司總部電話
  • 網(wǎng)站管理員可控的關(guān)鍵節(jié)點跨境電商怎么開店鋪
  • 網(wǎng)站開發(fā)培訓(xùn)課程百度seo關(guān)鍵詞排名查詢工具
  • 西安網(wǎng)站建設(shè)和推廣公司企業(yè)網(wǎng)站制作哪家好
  • 政務(wù)服務(wù)網(wǎng)站建設(shè)匯報谷歌優(yōu)化教程
  • 網(wǎng)站制作_做網(wǎng)站_耐思智慧找客源免費用哪個軟件好
  • 網(wǎng)站開發(fā)怎么收費青島新聞最新今日頭條
  • 設(shè)計比例網(wǎng)站北京網(wǎng)站優(yōu)化價格
  • 邢臺哪里可以做網(wǎng)站怎么引流怎么推廣自己的產(chǎn)品
  • 青州建網(wǎng)站seo高級優(yōu)化技巧
  • 外貿(mào)企業(yè) 訪問國外網(wǎng)站網(wǎng)絡(luò)營銷的基本方式有哪些
  • 導(dǎo)航網(wǎng)站是怎么做的建站系統(tǒng)源碼
  • 給網(wǎng)站寫文章怎么做無錫網(wǎng)站制作推廣