设计优化
善用设计模式
- 单例模式对于频繁使用创建对象和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中已经提供了相关的组件。
并行代替串行 硬件问题
负载均衡
时间换空间
空间换时间