享元模式

一、享元模式的意義?

享元模式重點在於享,可以理解爲分享,String的設計使用到了祥元模式,這個模式存在的意義在於減少創建許多冗餘的實例對象,造成OOM錯誤,比如在電商中,如果客戶請求一個商品就需要實例化一個商品對象,之後調用該對象的方方,一定會導致內存爆表的情況,享元模式會判斷對象是否已經存在於內存,如果存在則直接返回該對象,否則新建對象。

享元對象會區分內部狀態與外部狀態
內部狀態:不會隨着環境的改變而改變,比如電商中商品種類iphone
外部狀態:會隨着環境的改變而改變,比如電商商品中iphone版本號

二、享元模式結構

1、單純享元模式

在這裏插入圖片描述

  • 抽象享元(Flyweight)角色 :給出一個抽象接口,以規定出所有具體享元角色需要實現的方法。
  • 具體享元(ConcreteFlyweight)角色:實現抽象享元角色所規定出的接口。如果有內蘊狀態的話,必須負責爲內蘊狀態提供存儲空間。
  • 享元工廠(FlyweightFactory)角色 :本角色負責創建和管理享元角色。本角色必須保證享元對象可以被系統適當地共享。當一個客戶端對象調用一個享元對象的時候,享元工廠角色會檢查系統中是否已經有一個符合要求的享元對象。如果已經有了,享元工廠角色就應當提供這個已有的享元對象;如果系統中沒有一個適當的享元對象的話,享元工廠角色就應當創建一個合適的享元對象。

2、複雜享元模式

在這裏插入圖片描述
1、與單純享元模式相比,添加了複合享元,複合享元角色所代表的對象是不可以共享的,但是一個複合享元對象可以分解成爲多個本身是單純享元對象的組合。複合享元角色又稱作不可共享的享元對象。

三、單純享元模式實現

1、抽象享元(接口)

public interface IGoods {
	public void showPrice(String version);

}

2、具體享元(實現接口中的方法,其中包含內部狀態與外部狀態)

public class GoodsAbstract implements IGoods {
	private String name;//內部狀態
	private String version;//外部狀態
	public GoodsAbstract(String name) {
		this.name =name;
	}

	@Override
	public void showPrice(String version) {
		if(version=="32G") {
			System.out.println("價格爲5199");
		}else if (version=="64G") {
			System.out.println("價格爲6600");
		}

	}
	@Override
	public String toString() {
		return "商品爲:"+this.name;
	}

}

3、工廠模式,客戶端不需要去考慮對象的實例化,只需要去傳入商品類型於型號,工廠模式就要是避免創建過多的冗餘對象

import java.util.HashMap;

public class Factory {
	private HashMap<String, GoodsAbstract> map = new HashMap<>();
	public GoodsAbstract getGood(String name) {
		if(map.containsKey(name)) {
			System.out.println("獲取緩存的信息:"+map.get(name).toString());
			return map.get(name);
		}else {
			GoodsAbstract good = new GoodsAbstract(name);
			map.put(name, good);
			System.out.println("新建商品:"+map.get(name).toString());
			return map.get(name);
		}
	}

}

4、客戶端測試

public class ClientTest {
	public static void main(String[] args) {
		Factory factory = new Factory();
		GoodsAbstract good1 = factory.getGood("iphone7");
		good1.showPrice("32G");
		GoodsAbstract good2 = factory.getGood("iphone7");
		good2.showPrice("32G");
		GoodsAbstract good3 = factory.getGood("iphone7");
		good2.showPrice("64G");
		
	}

}

四、複合享元模式實現

1、複合商品

import java.util.HashMap;

public class CompositeGood implements IGoods {
	private HashMap<String, IGoods> coMap = new HashMap<>();

	// 增加一個單純享元添加到複合享元中
	public void add(String name, IGoods obj) {
		coMap.put(name, obj);
	}

	@Override
	// 外部狀態傳入
	public void showPrice(String version) {
		for (String name : coMap.keySet()) {
			System.out.println("所有手機類型:"+coMap.toString());
			if( name=="iphone" && version=="32G") {
				System.out.println("iphone價格爲5199");
			}else if (name=="iphone" &&version=="64G") {
				System.out.println("iphone價格爲6600");
			}
			if( name=="華爲" && version=="32G") {
				System.out.println("華爲價格爲5199");
			}else if (name=="華爲" &&version=="64G") {
				System.out.println("華爲價格爲6600");
			}
			if( name=="魅族" && version=="32G") {
				System.out.println("魅族價格爲5199");
			}else if (name=="魅族" &&version=="64G") {
				System.out.println("魅族價格爲6600");
			}
		}
	}

	@Override
	public String toString() {
		return "商品爲:" + this.coMap.toString();
	}

}

2、工廠模式(複合)

import java.util.ArrayList;
import java.util.HashMap;

public class Factory {
	private HashMap<String, GoodsAbstract> map = new HashMap<>();
	//單純享元工廠
	public IGoods getGood(String name) {
		if(map.containsKey(name)) {
			System.out.println("獲取緩存的信息:"+map.get(name).toString());
			return map.get(name);
		}else {
			GoodsAbstract good = new GoodsAbstract(name);
			map.put(name, good);
			System.out.println("新建商品:"+map.get(name).toString());
			return map.get(name);
		}
	}
	//複合享元工廠
	public IGoods getGood(ArrayList<String> list) {
		CompositeGood composite = new CompositeGood();
		for(String name:list) {
			composite.add(name, this.getGood(name));
		}
		return composite;
	}

}

3、測試

import java.util.ArrayList;

public class ClientTest {
	public static void main(String[] args) {
		//測試複合享元
		ArrayList<String> list = new ArrayList<>();
		list.add("iphone");
		list.add("華爲");
		list.add("魅族");
		CompositeGood cGood = (CompositeGood) factory.getGood(list);
		cGood.showPrice("32G");
		
		
	}

}

4、測試結果分析

//調用單純模式工廠方法,添加元素到複合模式存儲結構中
新建商品:商品爲:iphone
新建商品:商品爲:華爲
新建商品:商品爲:魅族
//遍歷所有手機類型,並且輸出32G對應手機的不同價格
所有手機類型:{華爲=商品爲:華爲, 魅族=商品爲:魅族, iphone=商品爲:iphone}
華爲價格爲5199
所有手機類型:{華爲=商品爲:華爲, 魅族=商品爲:魅族, iphone=商品爲:iphone}
魅族價格爲5199
所有手機類型:{華爲=商品爲:華爲, 魅族=商品爲:魅族, iphone=商品爲:iphone}
iphone價格爲5199

五、引用
【1】demo實例:http://liuwangshu.cn/designpatterns/12-flyweight.html
【2】複合享元模式:https://www.cnblogs.com/java-my-life/archive/2012/04/26/2468499.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章