享元模式
基本介绍
1.享元模式,又称蝇量模式:
2.运用共享技术实现大量细粒度对象的复用
应用
1.享元模式是池技术的重要实现方式
2.池技术:String 常量池、数据库连接池、缓冲池
3.常用于系统底层开发,解决系统的性能问题:如数据库连接池,池中是创建好的连接对象,若池中有符合需求的对象时直接用,避免重新创建;若池中没有符合需求的,则创建一个
要求
1.细粒度、共享对象
2..将对象的信息分为两个部分
(1)内部状态:指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变的状态
(2)外部状态:指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态
角色
1.FlyWeight:抽象的享元角色,产品的抽象类,定义了对象的外部状态和内部状态的接口或实现
2.ConcreteFlyWeight:具体的享元角色,产品的实现类,实现了抽象角色定义的相关业务
3.UnSharedConcreteFlyWeight:不可共享的角色,一般不会出现在享元工厂中
4.FlyWeightFactory:享元工厂类,内部提供一个池容器,储存ConcreteFlyWeight,同时提供从池中存取数据的操作
事项
1.享:共享,元:对象
2.应用场景:系统中有大量对象,这些对象消耗大量内存,并且对象的状态大部分可以外部化时
3.一般用 HashMap / HashTable 存储 ConcreteFlyWeight,key作为唯一标识码判断 ConcreteFlyWeight
4.优点
(1)解决重复对象的内存浪费的问题,减少了对象的创建,降低了程序内存的占用,提高效率
(2)提高了系统的复杂度,需要分离出内部状态和外部状态
5.缺点
(1)提高了系统的复杂度,需要分离出内部状态和外部状态。而外部状态具有固化特性,不应该随着内部状态的改变而改变
JDK 中的 Integer
public class Flyweight {
public static void main(String[] args) {
Integer a = Integer.valueOf(127);
Integer b = new Integer(127);
Integer c = Integer.valueOf(127);
System.out.println(a.equals(b));//true:a、b比较大小
System.out.println(a == b);//false:a是从池中取出的对象,b是直接new
System.out.println(a == c);//true:a、c都是从池中取出的对象
System.out.println(b == c);//false:c是从池中取出的对象,b是直接new
Integer d = Integer.valueOf(128);
Integer e = Integer.valueOf(128);
Integer f = new Integer(128);
System.out.println(d.equals(e));//true:d、e比较大小
System.out.println(d == e);//false:d、e超出范围,各自new一个对象
System.out.println(d == f);//false:d、f各自new一个对象
System.out.println(e == f);//false:e、f各自new一个对象
/*
public static Integer valueOf(int i) {
//IntegerCache是池,若i在池的范围内(-128<= i <= 127),从池取出
if (i >= Integer.IntegerCache.low && i <= Integer.IntegerCache.high)
return Integer.IntegerCache.cache[i + (-Integer.IntegerCache.low)];
//若i超出池的范围,则new一个,并装箱返回,但不会加入池中
return new Integer(i);
}
*/
}
}
代码示例
import java.util.HashMap;
public class Flyweight {//客户端
public static void main(String[] args) {
WebSiteFactory webSiteFactory = new WebSiteFactory();
User sina = new User("新浪");
User huawei = new User("华为");
User amazon = new User("亚马逊");
WebSite portal = webSiteFactory.getWebSiteCategory("门户类");
WebSite enterprise = webSiteFactory.getWebSiteCategory("企业类");
WebSite sale = webSiteFactory.getWebSiteCategory("销售类");
portal.use(sina);
enterprise.use(huawei);
sale.use(amazon);
System.out.println("网站类型总数:" + webSiteFactory.getWebSiteCount());
}
}
class WebSiteFactory {//享元工厂类
private HashMap<String, ConcreteWebSite> pool = new HashMap<>();//充当池的作用
//根据网站的类型,在池中返回一个网站
public WebSite getWebSiteCategory(String type) {
if (!pool.containsKey(type)) {
//若池中没有该类型的网站,在池中创建一个网站,并返回
pool.put(type, new ConcreteWebSite(type));
}
return pool.get(type);
}
//获取池中有多少个网站类型
public int getWebSiteCount() {
return pool.size();
}
}
abstract class WebSite {//抽象享元角色
public abstract void use(User user);
}
class ConcreteWebSite extends WebSite {//具体的享元角色
private String type;//内部状态
public ConcreteWebSite(String type) {
this.type = type;
}
@Override
public void use(User user) {
System.out.println("网站形式:" + type + ",用户:" + user.name);
}
}
class User {//不可共享角色
public String name;//外部状态
public User(String name) {
this.name = name;
}
}