Java 常見的設計模式
- Proxy 代理模式
- Factory 工廠模式
- Singleton 單例模式
- Delegate 委派模式
- Strategy 策略模式
- Prototype 原型模式
- Template 模板模式
- 代理模式是Java最常見的一種設計模式,客戶端不是直接調用實際的對象,而是通過代理,來間接調用實際對象。代理模式可分爲兩種, 靜態代理,動態代理
靜態代理:代碼實現:
package spring.service;
public interface ProxyService {
void say();
}
package spring.service.impl;
import spring.service.ProxyService;
public class RealProxy implements ProxyService{
private String name = "shanghai";
@Override
public void say() {
System.out.println(name);
}
}
package spring.service.impl;
import spring.service.ProxyService;
public class Real2Proxy implements ProxyService{
private String name = "beijing";
@Override
public void say() {
System.out.println(name);
}
}
package spring.service.impl;
import spring.service.ProxyService;
public class ProxyServiceImpl implements ProxyService{
private ProxyService service;
public ProxyServiceImpl(ProxyService service){
this.service = service;
}
@Override
public void say() {
service.say();
}
}
package spring.controller;
import spring.service.ProxyService;
import spring.service.impl.ProxyServiceImpl;
import spring.service.impl.Real2Proxy;
import spring.service.impl.RealProxy;
public class ProxyController {
public static void main(String[] args) {
ProxyService service = new ProxyServiceImpl(new RealProxy());
service.say();
ProxyService service1 = new ProxyServiceImpl(new Real2Proxy());
service1.say();
}
}
動態代理:也叫JDK代理,跟靜態代理差不多,也有種叫cglib 代理
package spring.service.impl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* JDK 代理
*/
public class DynamicProxy implements InvocationHandler{
private Object object;
public DynamicProxy(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = method.invoke(object, args);
return result;
}
}
cglib 代理,要導入 cglib jar,還可以用springcglib 代理
package spring.service.impl;
/**
* cglib 代理
* 目前類不能用final 修飾
* 方法不能用static final 修飾
*/
public class Cglib {
private String name = "java";
public void say(){
System.out.println(name);
}
}
package spring.service.impl;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Object object;
public CglibProxy(Object object){
this.object = object;
}
public Object getProxyInstance(){
//工具類
Enhancer en = new Enhancer();
//設置父類
en.setSuperclass(object.getClass());
//設置回調函數
en.setCallback(this);
//創建子類,(代理對象)
return en.create();
}
@Override
public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
Object result = method.invoke(object, args);
return result;
}
}
package spring.controller;
import spring.service.impl.Cglib;
import spring.service.impl.CglibProxy;
public class ProxyController {
public static void main(String[] args) {
//靜態
// ProxyService service = new ProxyServiceImpl(new RealProxy());
// service.say();
//
// ProxyService service1 = new ProxyServiceImpl(new Real2Proxy());
// service1.say();
//JDk代理
// DynamicProxy proxy = new DynamicProxy(new RealProxy());
// ProxyService service = (ProxyService) Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class[]{ProxyService.class}, proxy);
// service.say();
//cglib 代理
Cglib cg = (Cglib) new CglibProxy(new Cglib()).getProxyInstance();
cg.say();
}
}
總結:三種代理模式各有優缺點和相應的適用範圍,主要看目標對象是否實現了接口。以Spring框架所選擇的代理模式舉例
在Spring的AOP編程中:
如果加入容器的目標對象有實現接口,用JDK代理
如果目標對象沒有實現接口,用Cglib代理