Java程序优化之享元模式

155 阅读4分钟

享元模式主要目的是为了提高系统性能。它的核心思想是:如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用都创建新的对象。享元模式是为数不多的为提升系统性能而生的设计模式。

享元模式对性能提升主要有两点:

1·节省重复创建对象的开销,因为被享元模式维护的相同对象只会被创建一次,当创建对象比较耗时时,便可以节省大量时间。

2·由于创建的对象变少,所以对系统的内存需求也减少,使得GC压力相应降低,使系统有更快的反应速度。

享元模式主要角色有四个:享元工厂、抽象享元、具体享元类、主函数。

享元工厂:用于创建具体享元类,维护相同的享元对象。保证相同的享元独享可以被系统共享,当请求对象已存在,直接返回对象,不存在则创建对象。

抽象享元:定义共享的对象的业务接口。

具体享元:实现抽象享元类的接口,完成具体逻辑。

主函数:通过享元工厂获得享元对象

享元模式的核心是享元工厂,它需要确保系统可以共享相同的对象,一般情况下,享元工厂会维护一个对象列表,当需要获得享元对象时,有则直接返回,没有则创建新的享元对象,并将它添加到队列中。

以一个人事管理系统为例,三个公司甲、乙、丙是这个系统的用户,每个公司又有100个员工,每个员工都可以通过系统查询工资,为了系统安全,每个公司都有自己独立的数据库。这种情况可以使用享元模式,为每一个公司提供工资查询接口,一个公司下的所有人共享同一个查询(因为他们在同一个数据库,可以共享数据库连接),所以只需要三个享元实例,就能应对300个查询请求。


//享元接口类 用于创建报表

public interface IReportManager{

    public String createReport();

}

两个报表生成的实例类,分别对应员工收入报表和员工个人信息报表,都是享元类

//员工收入报表

public class FinanicReportManager implements IReportManager{

    protected String tenantId = null;

    public FinanicReportManager(String tenantId){

        this.tenantId = tenantId;

}

    public String createReport(){

        return "This is financial report"

        }

}



//员工个人信息报表

public class EmployeeReportManager implements IReportManager{

    protected String tenantId = null;

    public EmployeeReportManager(String tenantId){

        this.tenantId = tenantId;

}

    public String createReport(){

        return "This is financial report"

    }

}



//核心享元工厂类

public class ReportManagerFactory{

    //创建两个HashMap来存放实例类

    Map<String, IReportManager> financialReportManager = new HashMap<String,                 IReportManager>();

    Map<String, IReportManager> employeeReportManager = new HashMap<String,              IReportManager>();

    IReportManager getFinancialReportManager(String tenantId){

    IReportManager r = financialReportManager.get(tenantId);//通过ID获得享元

    if (r == null) {

            r = new FinanicReportManager(tenantId); //维护已创建的享元

            financialReportManager.put(tenantId, r);

        }

    return r;

    }

    IReportManager getEmployeeReportManager(String tenantId){

    IReportManager r = new employeeReportManager.get(tenantId);

    if (r == null) {

            r = new EmployeeReportManager(tenantId);

            employeeReportManager,put(tenantId, r);

        }

    return r;

    }

}



public static void main(String[] args) {

    ReportManagerFactory rmf = new ReportManagerFactory();

    IReportManager rm = rmf.getFinanicReportManager("A");

    System.out.println(rm.createReport());

}

享元工厂以ID为索引,维护一个享元的集合,确保相同公司的员工请求都返回同一个享元实例,确保享元对象的有效复用。