享元模式一般是使某个类的一个实例,提供许多虚拟实例的一种实现!Java String类型就实现了享元模式!
享元模式是为数不多的为提升性能而设计的模式!
享元模式的享元对象中的数据区分了内部状态和外部状态
内部状态:在享元对象中,不随外界环境改变而改变的共享部分的数据;
外部状态:在享元对象中,随着外界环境改变而改变的数据,不同虚拟对象不能共享!外部状态一般是在接口中,作为参数传入的!
享元模式中,一般包含如下几种角色:
抽象享元对象,规定了享元对象需要实现的接口;
具体享元角色,实现抽象享元对象规定的接口,一般由内部状态和外部状态两个维度!
享元工厂类,被客户端直接调用,一般包含一个容器用于存储已存在的享元对象,享元工厂类一般是单例模式!
需要注意的是,客户端不可以直接创建享元对象,只能通过享元工厂获取享元对象!
下面看一下具体实现:
首先定义抽象接口
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.flyweight; /** * @description * @author panteng * @date 17-2-20. */ public interface SnowDraw { void draw(int posX, int posY); }
定义具体的享元类
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.flyweight; /** * @description * @author panteng * @date 17-2-20. */ public class Snow implements SnowDraw { String size; public Snow(){ } public Snow(String inSize){ this.size = inSize; } public void draw(int posX, int posY){ System.out.println("大小:" + this.size + " 位置:" + posX + "," + posY); } public String getSize(){ return size; } public void setSize(String size){ this.size = size; } }
享元工厂类
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.flyweight; import java.util.HashMap; import java.util.Map; /** * @description 享元工厂类(单例) * @author panteng * @date 17-2-20. */ public class SnowFlyWeightFactory { static Map<Object, Snow> map = new HashMap<Object, Snow>(); private static SnowFlyWeightFactory singleSnowFlyWeightFactory; private SnowFlyWeightFactory(){ } public static SnowFlyWeightFactory getInstance(){ if (singleSnowFlyWeightFactory == null) { synchronized (SnowFlyWeightFactory.class) { singleSnowFlyWeightFactory = new SnowFlyWeightFactory(); } } return singleSnowFlyWeightFactory; } public Snow getSnow(String color){ if (map.keySet().contains(color)) { return map.get(color); } else { Snow snow = new Snow(color); map.put(color, snow); return snow; } } public static long getSize(){ return map.keySet().size(); } }
测试:
/* * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved */ package com.pt.flyweight; import org.junit.Test; import java.util.Random; /** * @description * @author panteng * @date 17-2-20. */ public class SnowFlyWeightFactoryTest { @Test public void flyWeightTest(){ Snow[] snows = new Snow[20]; for (int i = 0; i < snows.length; i++) { snows[i] = SnowFlyWeightFactory.getInstance().getSnow(new Random().nextInt(10) + ""); } for (int i = 0; i < snows.length; i++) { snows[i].draw(new Random().nextInt(9999), new Random().nextInt(9999)); } System.out.println("一共有:" + SnowFlyWeightFactory.getSize() + "个对象"); } }
外部状态是通过接口注入,然后和内部状态聚合的!
当有系统中需要大量对象,而这些对象的某些部分可以共享,这时候可以使用享元模式,节省内存!
===========================设计模式系列文章=========================