簡述 類型:結構型 目的:降低對象創建時大量屬性也隨之被新建而帶來的性能上的消耗 話不多說,我們看一個案例。 優化案例 最初版v0 現在需要採購一批辦公用的電腦,以下是Computer類的定義。 class Computer { private String sn; // 序列號,電腦的唯一識別碼 ...
簡述
- 類型:結構型
- 目的:降低對象創建時大量屬性也隨之被新建而帶來的性能上的消耗
話不多說,我們看一個案例。
優化案例
最初版v0
現在需要採購一批辦公用的電腦,以下是Computer
類的定義。
class Computer {
private String sn; // 序列號,電腦的唯一識別碼
private String brand; // 品牌
private String title; // 一個系列的名稱,如Lenovo的Thinkpad
private String cpu;
private String memory;
private String disk;
private String gpu;
private String keyboard;
private String display;
public Computer(String sn, String brand,
String title, String cpu,
String memory, String disk,
String gpu, String keyboard,
String display) {
this.sn = sn;
this.brand = brand;
this.title = title;
this.cpu = cpu;
this.memory = memory;
this.disk = disk;
this.gpu = gpu;
this.keyboard = keyboard;
this.display = display;
}
}
現在公司要採購兩種電腦總計1000台,以下是模擬採購的代碼。
class Client {
public static void main(String[] args) {
List<Computer> purchase = new ArrayList<>();
for (int i = 0; i < n; i ++) {
purchase.add(new Computer(UUID.randomUUID().toString(),
"華為", "MateBook16", "銳龍7 5800H標壓",
"16GB DDR4 雙通道", "512GB NVMe PCle SSD",
"gpu", "全尺寸背光鍵盤", "16英寸");
}
}
}
迴圈中每一次都要生成一個新的Computer對象,並且該對象中有很多String類型的屬性,因為String是一個引用數據類型,所以會隨之生成很多的引用,從而降低系統的性能。實際上,採購的電腦只要型號相同,配置參數也就隨之相同且不會再改變,唯一會改變的其實就只有機器的序列號而已,所以我們沒有每追加一臺電腦就重新設置一遍所有參數的必要。而且如果中途需要對於採購訂單的機器參數進行修改,那就必須迭代清單中的所有對象,對每個對象進行修改,又是一件效率低下的事。
為瞭解決這個問題,我們引入了享元模式。下麵是修改後的代碼。
修改版v1
class Computer {
private String sn; // 序列號,電腦的唯一識別碼
private ComputerSpec spec; // 依賴規格的具體屬性 → 依賴ComputerSpec類,迪米特法則
public Computer(String sn, ComputerSpec spec) {
this.sn = sn;
this.spec = spec;
this.title = title;
this.model = model;
this.cpu = cpu;
this.memory = memory;
this.disk = disk;
this.gpu = gpu;
this.keyboard = keyboard;
this.display = display;
}
}
enum ComputerSpec { // 定義一個電腦規格類
MATEBOOK16("華為", "MateBook16", "銳龍7 5800H標壓",
"16GB DDR4 雙通道", "512GB NVMe PCle SSD",
"gpu", "全尺寸背光鍵盤", "16英寸");
public String brand; // 品牌
public String title; // 一個系列的名稱,如Lenovo的Thinkpad
public String cpu;
public String memory;
public String disk;
public String gpu;
public String keyboard;
public String display;
ComputerSpec(String sn, String brand,
String title, String cpu,
String memory, String disk,
String gpu, String keyboard,
String display) {
this.brand = brand;
this.title = title;
this.model = model;
this.cpu = cpu;
this.memory = memory;
this.disk = disk;
this.gpu = gpu;
this.keyboard = keyboard;
this.display = display;
}
}
來看看修改後的採購如何模擬實現。
class Client {
public static void main(String[] args) {
List<Computer> purchase = new ArrayList<>();
for (int i = 0; i < n; i ++) {
purchase.add(new Computer(UUID.randomUUID().toString(),
ComputerSpec.MATEBOOK16));
}
// 由於訂單錯誤,現在需要批量將MateBook16修改為MateBook16s
ComputerSpec.MATEBOOK16.title = "MateBook16s";
}
}
使用享元模式,將Computer
對象創建時不變的屬性封裝到ComputerSpec
中,內部狀態與外部狀態分開,內部狀態直接引用相同的數據源,而不是每次都重新生成新的數據,從而大幅提升系統性能。並且,需要對於數據統一修改時,由於數據源引用相同,只需要修改內部狀態的對應屬性即可修改所有數據。
- 內部狀態:不可變對象。被共用的數據。如,案例中的
ComputerSpec
。 - 外部狀態:隨著業務而改變數據。不被共用的數據。如,案例中的
sn
。
總結
優點
- 由於多個對象的屬性引用相同,從而極大程度的降低了系統性能的消耗。
- 由於多個屬性被封裝成新的類,對象與屬性間的依賴減少,從而降低了對象創建的複雜度。
缺點
- 增加了開發人員對於系統業務理解的難度。
適用場景
- 當對象的絕大多數屬性與對象本身不是一對一而是一對多的關係時。換言之,多個對象公用一套屬性時。
本文來自博客園,作者:buzuweiqi,轉載請註明原文鏈接:https://www.cnblogs.com/buzuweiqi/p/16718920.html