1. 享元模式比较好理解,它的核心思想是:如果在一个系统中存在多个相同的对象,那么只需共享一份对象的拷贝,而不必为每一次使用都创建新的对象。
2. 享元模式对性能提升的主要帮助有两点:
a)可以节省重复创建对象的开销,当创建对象比较耗时时,便可以节省大量时间。
b)由于创建对象的数量减少,所以对系统内存的需求也减少,这将使得gc的压力也相应地降低。
3. 享元模式的主要角色
角色 | 作用 |
享元工厂 | 用以创建具有享元类,维护相同的享元对象,它保证相同的享元对象可以被系统共享。即,其内部使用了类似单例模式的算法,当请求对象已经存在时,直接返回对象,不存在时,在创建对象。 |
抽象享元 | 定义需共享的对象的业务接口,享元类被创建出来总是为了实现某些特定的业务逻辑,而抽象享元便定义这些逻辑的语义行为。 |
具体享元类 | 实现抽象享元类的接口,完成某一具体逻辑。 |
Main | 使用享元模式的组件 |
4. 享元模式经典案例:以一个人事管理系统的SASS软件案例为例,假设公司甲,乙,丙均为这个SASS系统的用户,则定义每个公司为这套系统的一个租户。每个公司(租户)又各有100个员工。如果这些公司的所有员工都可以登录这套系统查询自己的收入情况,并且为了系统安全,每个公司(租户)都拥有自己独立的数据库。为了使系统的设计最为合理,在这种情况下,便可以使用享元模式为每个租户分别提供工资查询的接口,而一个公司(租户)下的所有员工可以共享一个查询。这样,系统只需要3个享元实例,就足以应付300个员工的查询请求了。
5. 代码
抽象享元
public interface IReportManager
{
public String createReport();
}
具体享元类
public class FinancialReportManager implements IReportManager
{
protected String tenantId = null; //租户ID
public FinancialReportManager(String tenantId)
{
this.tenantId = tenantId;
}
@Override
public String createReport()
{
return "This is a financial report";
}
}
public class EmployeeReportManager implements IReportManager
{
protected String tenantId = null;
public EmployeeReportManager(String tenantId)
{
this.tenantId = tenantId;
}
@Override
public String createReport()
{
return "This is a employee report";
}
}
享元工厂
public class ReportManagerFactory
{
private Map<String, IReportManager> financialReportManager = new HashMap<String, IReportManager>(); //保存财务报表对象
private Map<String, IReportManager> employeeReportManager = new HashMap<String, IReportManager>(); //保存员工报表对象
//通过租户ID,获取享受元
public IReportManager getFinancialReportManager(String tenantId)
{
IReportManager r = financialReportManager.get(tenantId);
if(r == null)
{
r = new FinancialReportManager(tenantId); //维护已创建的享元对象
financialReportManager.put(tenantId, r);
}
return r;
}
public IReportManager getEmployeeReportManager(String tenantId)
{
IReportManager r = employeeReportManager.get(tenantId);
if(r == null)
{
r = new FinancialReportManager(tenantId);
employeeReportManager.put(tenantId, r);
}
return r;
}
}
Main
public class FunctionMain
{
public static void main(String[] args)
{
ReportManagerFactory rmf = new ReportManagerFactory();
IReportManager rm = rmf.getFinancialReportManager("A");
System.out.println(rm.createReport());
}
}