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


京公网安备 11010502036488号