设计优化

善用设计模式

  • 单例模式对于频繁使用创建对象和GC回收减轻压力

  • 代理模式屏蔽用户对真实对象的访问,主要是安全性和代理对象的轻量级性能提升。

动态代理:
JDK
public class JdkDbQueryHandler implements InvocationHandler{
    IDBQuery real=null;
    
    @Override
    public Object invoke(Object proxy,Method method,Object[] arges)throws Throwable{
        if(real==null){
            real=new DBQuery(); //如果是第一次使用,则生成真实对象
        }
        return real.request();  //使用真实主题完成实际操作
    }
}
public static IDBQuery createJdkProxy(){
    IDBQuery jdkProxy=(IDBQuery)Proxy.newProxyInstance(
    ClassLoader.getSystemClassLoader(),
        new Class[](IDBQuery.class),
    new JdkDbQueryHandler()
    );
    
    return jdkProxy;
}
CGLIB
public class CglibDbQueryInterceptor implements MethodInterceptor{
    IDBQuery real=null;
    
    @Override
    public Object intercept(Object arg0,method arg1,Object[] arg2,MethodProxy arg3)throws Throwable{
        if(real==null){
            real=new DBQuery();
        }
        return real.request();
    }
    
    public static IDBQuery createCglibProxy(){
        Enhancer enhancer=new Enhancer();
        enhancer.setCallback(new CglibDbQueryInterceptor());
        enhancer.setInterfaces(new Class[] {IDBQuery.class});
        
        IDBQuery cglibProxy=(IDBQuery)enhancer.create();
        return cglibProxy;
        
    }
}
  • 享元模式为系统多个相同对象提供一份共享的对象,节省重复创建对象的开销,GC压力也相应减少。

享元模式和对象池的最大不同在于:享元对象是不可相互替代的,它们各自都有的含义和用途;而对象池中的对象是等价的,如数据库连接池中数据库的连接。
public interface IReportManager{
    public String createReport();  //用以创建一个报表,所有的报表生成类将作为享元对象在一个租户***享
}
public class FinacialReportManager implements IReportManager{//具体的享元类
    protected String tenantId=null;
    
    public FinacialReportManager(String tenantId){
        this.tenantId=tenantId;
    }
    @Override
    public String createReport(){
        return "This is a financial report";
    }
}

public class EmployeeReportManager implements IReportManager{//具体的享元类
    protected String LenantId=null;
    public EmployeeReportManager(String tenantId){
        this.tenantId=tenantId;
    }
    @Override
    public String createReport(){
        return "This is an employee report";
    }
}
最核心的享元类实现如下:
public class ReportManagerFactory{
    Map<String,IReportManager> financialReportManager=new HashMap<String,IReportManager>();
    
    Map<String,IReportManager> employeeReportManager=new HashMap<String,IReportManager>();
    
    IReportManager getFincialReportManager(String tenantId){//通过租户id获取享元
        IReportManager r=financialReportManager.get(tenantId);
        if(r==null){
            r=new FinacialReportManager(tenantId);
            financialReportManager.put(tenantId,r);
        }
        return r;
    }
    
    IReportManager getEmployeeReportManager(String tenantId){//通过租户id获取享元
        IReportManager r=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.getFinancialReportManager("A");
    System.out.println(rm.createReport());
}
  • 装饰者模式充分运用委托机制,复用系统中的各个组件,取代耦合紧密的继承,动态添加对象功能。


public interface IPackCreator{
    public String handleContent();
}

public class PacketBodyCreator implements IPacketCreator{
    @Override
    public String handleContent(){
        return "Content of Packet";
    }
}
public abstract class PacketDecorator implements IPacketCreator{
    IPacketCreator component;   //该类的作用是增强功能
    public PacketDecorator(IPacketCreator c){
        component=c;
    }
}

public class PacketHTMLHeaderCreator extends PacketDecorator{
    public PacketHTMLHeaderCreator(IPacketCreator c){
        super(c);
    }
    
    @Override
    public String handleContent(){
        StingBuffer sb=new StringBuffer();
        sb.append("");
    }
}
  • 观察者模式用于当一个对象的行为依赖于另一个对象的状态时

public interface ISubject{
    void attach(IOberver observer);    //添加观察者
    void detach(IObserver observer);   //删除观察者
    void inform();    //通知所有观察者
}

public interface IObserver{
    void update(Event evt);   //更新观察者
}
public class ConcreteSubject implements ISubject{
    vector<IObserver> observers=new Vector<>();
    
    public void attach(IObserver observer){
        observers.addElement(observer);
    }
    public void detach(IObserver observer){
        observers.removeElement(observer);
    }
    public void inform(){
        Event evt=new Event();
        for(IObserver ob:observers){
            ob.update(evt);
        }
    }
}
JDK内置观察者模式:


此外还有将对象序列化传递并封装属性为一个对象的valueObject模式
将远程方法调用的业务流程封装在一个位于展示层的代理类中。

常用优化组件和方法

缓冲区是一块特定的内存区域,开辟缓冲区的目的是通过缓解应用程序上下层之间的性能差异。
最常见的场景是I/O的速度。
Writer writer=new FileWriter(new File("file.txt"));
long begin=System.currentTimeMillis();
for(int i=0;i<CIRCLE;i++){
    writer.write(i);   //写入文件
}
writer.close();
System.out.println(System.currentTimeMillis()-begin);


Writer writer=new BufferedWriter(new FileWriter(new File("file.txt"))); //增加了缓冲
long begin=System.currentTimeMillis();
for(int i=0;i<CIRCLE;i++){
    writer.write();
}
writer.close();
System.out.println(System.currentTimeMillis()-begin);
BufferedWriter(Writer out,int sz)构造函数指定了缓冲的大小
BufferedOutputStream(OutputStream out,int siz) 制定了缓冲大小

缓存也是为提升系统性能开辟的内存空间,暂存数据的处理结果,并提供下次访问。
目前浏览器中的本地缓存就是例子。
最简单的缓存使用HashMap实现,如何清理无效数据,如何防止数据过多导致的内存溢出,因此可以直接使用WeakHashMap,他使用弱引用来维护一种哈希表,从而避免了潜在的内存溢出。
目前常见基于java的缓存框架:EHCache  OSCache  JBossCache    
EHCache:是Hibernate默认的方案。

对象复用---池:如果一个类被频繁的请求使用,那么可以保存在一个池中,待需要使用的时候直接从池中获取,这个池被称为对象池。
对象池可能是一个数组,一个链表任意集合类。熟悉的有线程池,数据库连接池。目前广泛使用的有:C3P0和Proxool
Hibernate伴随着C3P0使用:

关于对象池的开发,Apache中已经提供了相关的组件。

并行代替串行  硬件问题

负载均衡

时间换空间

空间换时间