概念:
享元模式(Flyweight Pattern)是一种软件设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
经典应用场景:
来复习下Java中String类型的特性:String类型的对象一旦被创造就不可改变;当两个String对象所包含的内容相同的时候,JVM只创建一个String对象对应这两个不同的对象引用。让我们来验证实下着两个特性吧
先来验证下第二个特性:
public class TestPattern {
public static void main(String[] args){
String n = "Java design"; String m = "Java design"; System.out.println(n==m); m=m+" pattern"; System.out.println(n==m);
}
}
这段代码会告诉你n==m是true,这就说明了在JVM中n和m两个引用了同一个String对象。之后在系统输出之前加入一行代码”m=m+" pattern";”,这时候n==m结果为false,刚才两个还是引用的对象,已经不同了?原因就是在执行后添加语句时,m指向了一个新创建的String对象,而不是修改引用的对象。
JAVA String类型的设计避免了在创建N多的String对象时产生的不必要的资源损耗,可以说是享元模式应用的范例,下面来看看怎么在自己的程序中使用享元模式。
实现:
在享元模式中,由于要产生各种各样的对象,所以在Flyweight(享元)模式中常出现Factory模式。Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个对象存储池(Flyweight Pool)来存放内部状态的对象。Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度.应用场合很多。
案例:
项目需要建立城市地区数据,包括城市名,上级辖区等。
Area 类:
public abstract class Area { private String name; public abstract void displayName(); public abstract Area setAdminArea(Area area); public abstract Area getAdminArea(); public Area setName(String areaname) { name = areaname; return this; } public String getName() { return name; } }
City 类:
public class City extends Area { private Area adminArea; @Override public void displayName() { System.out.println(getName()); } public Area getAdminArea() { return adminArea; } @Override public Area setAdminArea(Area area) { this.adminArea = area; return this; } }
AdminArea 类:
public class AdminArea extends Area { public AdminArea(String areaname) { super(); setName(areaname); } @Override public void displayName() { System.out.println(getName()); } @Override public Area setAdminArea(Area area) { return null; } @Override public Area getAdminArea() { return null; } }
AdminAreaFactory 工厂类:
public class AdminAreaFactory { private static Hashtable hashtable = new Hashtable(); public static Area produce(String name){ if(null==name){ return null; } Area area = (Area) hashtable.get(name); if(null==area){ area = new AdminArea(name); hashtable.put(name,area); } return area; } public static int getObjectCount(){ return hashtable.size(); } }
测试类:
public class WorkClass { public void test() { Area city0 = new City().setName("hangzhou") .setAdminArea(AdminAreaFactory.produce("zhejiang")); Area city1 = new City().setName("suzhou") .setAdminArea(AdminAreaFactory.produce("jiangsu")); Area city2 = new City().setName("huzhou") .setAdminArea(AdminAreaFactory.produce("zhejiang")); Area city3 = new City().setName("nanjing") .setAdminArea(AdminAreaFactory.produce("jiangsu")); Area city4 = new City().setName("ninbo") .setAdminArea(AdminAreaFactory.produce("zhejiang")); List list = new ArrayList(); list.add (city0); list.add (city1); list.add (city2); list.add (city3); list.add (city4); for (int i = 0; i < list.size(); i++) { Area city = list.get(i); city.getAdminArea().displayName(); city.displayName(); } System.out.println(String.format("AdminAreaFactory.getObjectCount()=%s", AdminAreaFactory.getObjectCount())); } }
测试结果输出:
06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: zhejiang 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: hangzhou 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: jiangsu 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: suzhou 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: zhejiang 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: huzhou 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: jiangsu 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: nanjing 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: zhejiang 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: ninbo 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: AdminAreaFactory.getObjectCount()=2
通过AdminAreaFactory的管理,实现了AdminArea的共享,不需要每一次都重新创建对象,节省了系统开销。