設計模式十五之亨元模式(java)
這是我看Head first設計模式書籍之後想要總結的知識點,一方面是對自己學習的東西總結和提煉加強自己的理解和記憶,另一方面是給大家簡化這本書,方便大家快速瞭解各種設計模式。
我想提醒大家的是,設計模式只是前人總結的一些經驗套路,實際上還是要在開發專案中慢慢體會,不可成為設計模式的中毒患者,強行照搬設計模式的一些規則。
(1) 亨元模式 亨元模式(Flyweight Pattern)主要用於減少建立物件的數量,以減少記憶體佔用和提高效能。這種型別的設計 屬於結構型模式,它提供了減少物件數量從而改善應用所需的物件結構的方式。 在亨元模式中可以共享的相同內容成為內部狀態(Intrinsic State),而那些需要外部環境來設定的不能共享的 內容成為外部狀態(Extrinsic State),其中外部狀態和內部狀態是相互獨立的,外部狀態的變化不會引起內部 狀態的變化。由於區分了內部狀態和外部狀態,因此可以通過設定不同的外部狀態使得相同的物件可以具有一些 不同的特徵,而相同的內部狀態是可以共享的。也就是說亨元模式就是把一個物件的狀態分成內部狀態和外部狀態, 內部狀態即是不變的,外部狀態是變化的;然後通過共享不變的部分,達到減少物件數量並節約記憶體的目的。 在亨元模式中通常會出現工廠模式,需要建立一個亨元工廠來負責維護一個亨元池(Flyweight Pool)(用於 儲存具有相同內部狀態的亨元物件)。在亨元模式中,共享的亨元物件的內部狀態,外部狀態需要通過環境來設定。在 實際使用中,能夠共享的內部狀態是有限的,因此亨元物件一般都設計為較小的物件,它所包含的內部狀態較少,這種物件 也成為細粒度物件。亨元模式的目的就是使用共享技術來實現大量細粒度物件的複用。 由於亨元模式要求能夠共享的物件必須是細粒度物件,因此它又稱為輕量級模式,它是一種物件結構型模式。
(2) 模式所涉及的角色 Flyweight: 亨元介面,通過這個介面傳入外部狀態並作用於外部狀態 ConcreteFlyweight: 具體的亨元實現物件,必須是可共享的,需要封裝亨元物件的內部狀態 UnsharedConcreteFlyWeight: 非共享的亨元實現物件,並不是所有的亨元物件都可以共享,非 共享的亨元物件通常是亨元物件的組合物件。 FlyweightFactory: 亨元工廠,主要用來建立並管理共享的亨元物件,並對外提供訪問共享亨元的介面。
(3) 亨元模式嘗試重用現有的同類物件,如果未找到匹配的物件,則建立新物件。我們將通過建立5個物件來畫出20 個分佈不同位置的圓來演示這種模式。由於只有5種可用的顏色,所以color屬性被用來檢查現有的Circle物件意圖:
優點: 大大減少物件的建立,降低系統的記憶體,使效率提高。缺點: 提高了系統的複雜度,需要分離出外部狀態和內部狀態,而且外部狀態具有固有化的性質,不應該隨著內部狀態的變化而變化,否則會造成系統的混亂。使用場景: 1.系統有大量相似物件 2.需要緩衝池的場景注意事項:
1.注意劃分外部狀態和內部狀態,否則可能會引起執行緒安全問題 2.這些類必須有一個工廠物件加以控制。
實現 我們將建立一個Shape介面和實現了Shape介面的實體類Circle.下一步是定義工廠類ShapeFactory ShapeFactory有一個Circle的HashMap,其中鍵名為Circle物件的顏色。無論何時接受到請求,都會建立一個特定 顏色的圓。ShapeFactory檢查它的HashMap中的circle物件,如果找到Circle物件,則返回該物件,否則將建立一個儲存 在hashmap中以備後續使用的新物件,並把該的物件返回到客戶端。 FlyWeightPatternDemo,我們的演示類使用ShapeFactory來獲取Shape物件。它將向ShapeFactory傳遞資訊(red/green/blue/black/ white),以便獲取它所需物件的顏色。
建立一個介面 Shape.java
package com.gougoucompany.designpattern.flyweight;
//建立一個介面
public interface Shape {
void draw();
}
建立實現介面的實體類Circle.java
package com.gougoucompany.designpattern.flyweight;
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;
public Circle(String color) {
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("Cicle: Draw() [Color : " + color
+ ", x: " + x + ", y: " + y + ", radius: " + radius);
}
}
建立一個工廠,生成基於給定資訊的實體類物件ShapeFactory.java
package com.gougoucompany.designpattern.flyweight;
import java.util.HashMap;
public class ShapeFactory {
//HashTable是執行緒安全的,其實現方式是在對應的方法上加上synchronized關鍵字,效率不高
private static final HashMap<String, Shape> circleMap =
new HashMap<>();
public static Shape getCircle(String color) {
/*
Returns the value to which the specified key
is mapped, or null if this map contains no mapping
for the key.
*/
Circle circle = (Circle)circleMap.get(color);
//如果沒有快取在,則重新建立,這個和安卓開發的RecyclerView快取類似
if(circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color : " + color);
}
return circle;
}
}
使用該工廠,通過傳遞顏色資訊來獲取實體類的物件FlyweightPatternDemo.java
package com.gougoucompany.designpattern.flyweight;
public class FlyweightPatternDemo {
private static final String colors[] =
{"Red", "Green", "Blue", "White", "Black"};
public static void main(String args[]) {
for(int i = 0; i < 20; ++i) {
Circle circle =
(Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
private static String getRandomColor() {
return colors[(int)(Math.random() * colors.length)];
}
private static int getRandomX() {
return (int)(Math.random() * 100);
}
private static int getRandomY() {
return (int)(Math.random() * 100);
}
}
result:
result:
Creating circle of color : White
Cicle: Draw() [Color : White, x: 56, y: 56, radius: 100
Creating circle of color : Green
Cicle: Draw() [Color : Green, x: 85, y: 5, radius: 100
Creating circle of color : Red
Cicle: Draw() [Color : Red, x: 92, y: 95, radius: 100
Cicle: Draw() [Color : Red, x: 72, y: 88, radius: 100
Cicle: Draw() [Color : Green, x: 61, y: 48, radius: 100
Cicle: Draw() [Color : Green, x: 26, y: 85, radius: 100
Cicle: Draw() [Color : Green, x: 39, y: 31, radius: 100
Cicle: Draw() [Color : Green, x: 53, y: 77, radius: 100
Creating circle of color : Black
Cicle: Draw() [Color : Black, x: 81, y: 15, radius: 100
Cicle: Draw() [Color : Green, x: 41, y: 70, radius: 100
Creating circle of color : Blue
Cicle: Draw() [Color : Blue, x: 87, y: 36, radius: 100
Cicle: Draw() [Color : Blue, x: 72, y: 80, radius: 100
Cicle: Draw() [Color : White, x: 61, y: 28, radius: 100
Cicle: Draw() [Color : Red, x: 97, y: 20, radius: 100
Cicle: Draw() [Color : White, x: 16, y: 99, radius: 100
Cicle: Draw() [Color : Green, x: 91, y: 35, radius: 100
Cicle: Draw() [Color : Blue, x: 66, y: 64, radius: 100
Cicle: Draw() [Color : White, x: 3, y: 75, radius: 100
Cicle: Draw() [Color : Green, x: 4, y: 82, radius: 100
Cicle: Draw() [Color : Green, x: 58, y: 39, radius: 100