java設(shè)計模式之-享元模式
什么是享元模式?
享元模式是一種結(jié)構(gòu)型設(shè)計模式,旨在通過共享對象來最大程度地減少內(nèi)存使用和提高性能。它通過將對象的狀態(tài)分為內(nèi)部狀態(tài)和外部狀態(tài),將可共享的內(nèi)部狀態(tài)存儲在對象池中,并在需要時共享給多個對象,從而減少了重復創(chuàng)建相似對象的成本。主要解決什么問題?
享元模式主要解決大量細粒度對象的內(nèi)存消耗問題。在某些情況下,如果每個對象都獨立地存儲了大量相似的數(shù)據(jù),將導致內(nèi)存消耗過高。通過共享對象,我們可以顯著減少內(nèi)存使用,提高系統(tǒng)的整體性能。在什么時候我們需要使用享元模式?
當滿足以下條件時,考慮使用享元模式:
系統(tǒng)中存在大量相似的對象。
創(chuàng)建這些對象的開銷很大,導致內(nèi)存消耗過高。
對象的狀態(tài)可以被分為內(nèi)部狀態(tài)和外部狀態(tài),其中內(nèi)部狀態(tài)可以被共享。
用一個生活中的應用實例來舉例、類比
假設(shè)您正在開發(fā)一個繪圖應用程序,用戶可以繪制各種形狀(如圓形、矩形等)。在這種情況下,每個形狀對象都有一些相同的屬性,比如顏色、線條粗細等,以及一些特定于該形狀的屬性,比如半徑、寬度和高度。在不使用享元模式的情況下,每次用戶繪制一個新形狀時,都會創(chuàng)建一個全新的對象,這將導致內(nèi)存消耗增加。而使用享元模式,您可以將共享的屬性(如顏色)作為內(nèi)部狀態(tài)存儲在對象池中,每次用戶繪制時,只需為特定的屬性(如半徑)創(chuàng)建一個新對象,從而減少了內(nèi)存占用。優(yōu)點
減少內(nèi)存消耗:通過共享內(nèi)部狀態(tài),減少了需要創(chuàng)建的對象數(shù)量,從而降低了內(nèi)存消耗。
提高性能:復用現(xiàn)有對象可以避免頻繁創(chuàng)建和銷毀對象的開銷,從而提高系統(tǒng)性能。
簡化對象管理:享元模式將對象的狀態(tài)分為內(nèi)部狀態(tài)和外部狀態(tài),簡化了對象的管理和維護。
缺點
引入了對象共享,可能會增加系統(tǒng)的復雜性。
對象共享可能會導致線程安全問題,需要注意并發(fā)訪問的同步控制。
使用場景
享元模式適用于以下情況:
系統(tǒng)中存在大量相似的對象,且創(chuàng)建這些對象的開銷較大。
對象的大部分狀態(tài)可以被外部化,剩余部分可以通過共享實現(xiàn)。
下面是一個簡單的Java代碼示例:
import java.util.HashMap;
import java.util.Map;
// 圖形接口
interface Shape {
? ? void draw();
}
// 具體圖形類
class Circle implements Shape {
? ? private String color;
? ? public Circle(String color) {
? ? ? ? this.color = color;
? ? }
? ? public void draw() {
? ? ? ? System.out.println("繪制了一個" + color + "的圓形");
? ? }
}
// 圖形工廠類
class ShapeFactory {
? ? private static final Map<String, Shape> circleMap = new HashMap<>();
? ? public static Shape getCircle(String color) {
? ? ? ? Circle circle = (Circle) circleMap.get(color);
? ? ? ? if (circle == null) {
? ? ? ? ? ? circle = new Circle(color);
? ? ? ? ? ? circleMap.put(color, circle);
? ? ? ? ? ? System.out.println("創(chuàng)建了一個" + color + "的圓形");
? ? ? ? ? ? ? ?} else {
? ? ? ? ? ? System.out.println("獲取了一個" + color + "的圓形");
? ? ? ? }
? ? ? ? return circle;
? ? }
}
// 示例代碼
public class Main {
? ? public static void main(String[] args) {
? ? ? ? String[] colors = {"紅色", "綠色", "藍色", "紅色"};
? ? ? ? for (String color : colors) {
? ? ? ? ? ? Shape shape = ShapeFactory.getCircle(color);
? ? ? ? ? ? shape.draw();
? ? ? ? }
? ? }
}
在上述示例中,Circle
?表示具體的圓形對象,ShapeFactory
?是圖形工廠類,負責創(chuàng)建和管理圓形對象。ShapeFactory
?使用?circleMap
?字典來緩存已創(chuàng)建的圓形對象。當需要獲取一個圓形對象時,首先在字典中查找是否存在對應顏色的圓形對象,如果存在則返回已有的對象,否則創(chuàng)建一個新的圓形對象并將其添加到字典中。
當運行示例代碼時,可以看到只有第一次創(chuàng)建圓形對象時會輸出"創(chuàng)建了一個顏色的圓形",后續(xù)獲取相同顏色的圓形對象時會輸出"獲取了一個顏色的圓形"。這說明通過享元模式,我們成功地實現(xiàn)了圓形對象的共享,減少了對象的創(chuàng)建和內(nèi)存消耗。