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代理