天天看點

Java結構型模式(1)享元模式

2019年阿裡雲雙11活動拼團: https://www.aliyun.com/1111/2019/group-buying-share

一、概述

享元模式:“享”就是分享之意,指一物被衆人共享,而這也正是該模式的終旨所在。

享元模式有點類似于單例模式,都是隻生成一個對象來被共享使用。這裡有個問題,那就是對共享對象的修改,為了避免出現這種情況,我們将這些對象的公共部分,或者說是不變化的部分抽取出來形成一個對象。這個對象就可以避免到修改的問題。

享元的目的是為了減少不會要額記憶體消耗,将多個對同一對象的通路集中起來,不必為每個通路者建立一個單獨的對象,以此來降低記憶體的消耗。

二、示例

下面我們來看一個簡單的例子:

建築接口:JianZhu

public interface Jianzhu {
    void use();
}           

體育館實作類:TiYuGuan

public class TiYuGuan implements Jianzhu {
    private String name;
    private String shape;
    private String yundong;
    public TiYuGuan(String yundong){
        this.setYundong(yundong);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getShape() {
        return shape;
    }
    public void setShape(String shape) {
        this.shape = shape;
    }
    public String getYundong() {
        return yundong;
    }
    public void setYundong(String yundong) {
        this.yundong = yundong;
    }
    @Override
    public void use() {
        System.out.println("該體育館被使用來召開奧運會" + "  運動為:"+ yundong+"  形狀為:"+shape+ "  名稱為:"+name);
    }
}           

建築工廠類:JianZhuFactory

import java.util.*;

public class JianZhuFactory {
    private static final Map<String,TiYuGuan> tygs = new HashMap<String,TiYuGuan>();
    public static TiYuGuan getTyg(String yundong){
        TiYuGuan tyg = tygs.get(yundong);
        if(tyg == null){
            tyg = new TiYuGuan(yundong);
            tygs.put(yundong,tyg);
        }
        return tyg;
    }
    public static int getSize(){
        return tygs.size();
    }
}           

測試類:Clienter

public class Clienter {
    public static void main(String[] args) {
        String yundong ="足球";
        for(int i = 1;i <= 5;i++){
            TiYuGuan tyg = JianZhuFactory.getTyg(yundong);
            tyg.setName("中國體育館");
            tyg.setShape("圓形");
            tyg.use();
            System.out.println("對象池中對象數量為:"+JianZhuFactory.getSize());
        }
    }
}           

執行結果:

該體育館被使用來召開奧運會  運動為:足球  形狀為:圓形  名稱為:中國體育館
對象池中對象數量為:1
該體育館被使用來召開奧運會  運動為:足球  形狀為:圓形  名稱為:中國體育館
對象池中對象數量為:1
該體育館被使用來召開奧運會  運動為:足球  形狀為:圓形  名稱為:中國體育館
對象池中對象數量為:1
該體育館被使用來召開奧運會  運動為:足球  形狀為:圓形  名稱為:中國體育館
對象池中對象數量為:1
該體育館被使用來召開奧運會  運動為:足球  形狀為:圓形  名稱為:中國體育館
對象池中對象數量為:1           

三、模式解析

如上示例中,使用工廠模式進行配合,建立對象池,測試類中的循環,你可以想象成為要舉行5場比賽,每場比賽的場地就是體育館

通過執行結果可以看出,在這個對象池(HashMap)中,一直都隻有一個對象存在,第一次使用的時候建立對象,之後的每次調用都用的是那個對象,不會再重新建立。

其實在Java中就存在這種類型的執行個體:String。

Java中将String類定義為final(不可改變的),JVM中字元串一般儲存在字元串常量池中,這個字元串常量池在jdk 6.0以前是位于常量池中,位于永久代,而在JDK 7.0中,JVM将其從永久代拿出來放置于堆中。           
我們使用如下代碼定義的兩個字元串指向的其實是同一個字元串常量池中的字元串值。           
String s1 = "abc";
String s2 = "abc";           

如果我們以s1==s2進行比較的話所得結果為:true,因為s1和s2儲存的是字元串常量池中的同一個字元串位址。這就類似于我們今天所講述的享元模式,字元串一旦定義之後就可以被共享使用,因為他們是不可改變的,同時被多處調用也不會存在任何隐患。

四、使用場景

當我們項目中建立很多對象,而且這些對象存在許多相同子產品,這時,我們可以将這些相同的子產品提取出來采用享元模式生成單一對象,再使用這個對象與之前的諸多對象進行配合使用,這樣無疑會節省很多空間。