一、享元模式的意义?
享元模式重点在于享,可以理解为分享,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