享元模式定义如下:运用共享技术有效地支持大量细粒度的对象。
享元模式使用共享对象技术,用来尽可能的减少内存使用量,适合用于当大量对象只是重复,因而导致无法令人接受的、使用大量内存的情况。通常对象中的部分状态是可以共享的,常见做法是把他们放在外部数据结构,当需要使用时再将它们传递给享元。
适合享元模式的情景如下:
- 对大量对象而言,许多属性都是相同的,一旦创建则不能修改
- 对象的多数状态都可变为外部状态
享元模式各种角色描述:
- 抽象享元角色(IFlyweight):此角色是所有具体享元的超类,为这些类规定出需要实现的公共接口(或抽象类)方法。
- 具体享元(ConcreteFlyweight)角色:实现抽象享元角色所定义的接口方法。如果有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。
- 享元工厂(FlyweightFactory):本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端请求一个享元对象的时候,享元工厂角色需要检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。
假设我们正在编制一个学生信息管理类,学生的基本属性包括:学号、姓名、年龄、所在大学、所在市、以及邮编等信息。前三个属性与个体有关,后三个属性一般来说属于共性信息,即对一所具体大学的所有学生而言,后三个属性的值是不变的。
利用享元模式编写学生信息基本类:
(1)定义抽象享元角色 IFlyweight
对于每个学生信息而言,城市 大学 省份是共享信息,因此定义了获得这三个信息的抽象方法。
public interface IFlyweight {
String getUniversity();
String getCity();
String getProvince();
}
(2)具体享元类Flyweight
通过构造方法Flyweight() 创建了享元对象,并重写了三个 get方法。
public class Flyweight implements IFlyweight{
private String university;
private String city;
private String province;
public Flyweight(String university, String city, String province) {
this.university = university;
this.city = city;
this.province = province;
}
@Override
public String getUniversity() {
return university;
}
@Override
public String getCity() {
return city;
}
@Override
public String getProvince() {
return province;
}
}
(3)享元工厂类 FlywightFactory
该类采用了单例模式,成员变量容器map定义了“键-享元对象”的映射。addFlyweight() 方法用于向map容器中添加享元对象;getFlyWeight() 方法从map中获取享元对象。
public class FlyweightFactory {
private FlyweightFactory(){}
private static FlyweightFactory factory = new FlyweightFactory();
private Map map = new HashMap<>();
//单例模式 完全同步方式
public synchronized static FlyweightFactory getInstance(){
return factory;
}
public void addFlyweight(String key, IFlyweight fly) {
map.put(key,fly);
}
public synchronized IFlyweight getFlyWeight(String key) {
IFlyweight obj = map.get(key);
return obj;
}
}
(4)学生基本信息类StudInfo
name age是个体变量,flyweight是共享变量
public class StudInfo {
private String name;
private int age;
private IFlyweight flyweight;
public StudInfo(String n, int a, IFlyweight f) {
name = n;
age = a;
flyweight = f;
}
public void display() {
System.out.println("name="+name);
System.out.println("age="+age);
System.out.println("university="+flyweight.getUniversity());
System.out.println("city="+flyweight.getCity());
System.out.println("province="+flyweight.getProvince());
}
}
(5)测试类
初始时享元工厂factory是空的,将所需要的享元对象fly,fly2添加到享元工厂中。在建立学生对象前,要先从享元工厂中获取所需的享元对象,之后才能建立学生对象。
public class Test {
public static void main(String[] args) {
//工厂实例
FlyweightFactory factory = FlyweightFactory.getInstance();
//定义两个享元对象
IFlyweight flyweight = new Flyweight("长安大学","西安","陕西");
IFlyweight flyweight2 = new Flyweight("山西医科大学","太原","山西");
//添加到享元工厂中
factory.addFlyweight("one", flyweight);
factory.addFlyweight("two", flyweight2);
//从享元工厂中获得享元对象
IFlyweight obj = null;
obj = factory.getFlyWeight("one");
IFlyweight obj2 = null;
obj2 = factory.getFlyWeight("two");
StudInfo student = new StudInfo("zhangyin",25,obj);
StudInfo student2 = new StudInfo("minmin",22,obj2);
student.display();
System.out.println("==========================================");
student2.display();
}
}
输出:
name=zhangyin
age=25
university=长安大学
city=西安
province=陕西
==========================================
name=minmin
age=22
university=山西医科大学
city=太原
province=山西