23种设计模式完整教程
介绍
代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问。 代理对象在客服端和目标对象之间起到中介作用,代理模式属于结构型设计模式。
在生活中,我们经常见到这样的场景,如:租房中介、售票黄牛、婚介、经纪人、快递、 事务代理、非侵入式日志监听等,这些都是代理模式的实际体现。
目的
1、保护目标对象
2、增强目标对象。
分类
1、静态代理
2、动态代理
动态代理与静态代理的区别
1、静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步 新增,违背开闭原则。
2、动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开 闭原则。
3、若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成, 无需修改代理类的代码。
优点
1、代理模式能将代理对象与真实被调用的目标对象分离。
2、一定程度上降低了系统的耦合度,扩展性好。
3、可以起到保护目标对象的作用。
4、可以对目标对象的功能增强。
缺点
1、代理模式会造成系统设计中类的数量增加。
2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
3、增加了系统的复杂度。
使用场景
1、日志监听
2、保护目标对象或则增强目标对象
3、Spring 利用动态代理实现 AOP 有两个非常重要的类,一个是 JdkDynamicAopProxy 类 和 CglibAopProxy 类。
4、有分库场景时,数据库的动态选择---可考虑这种模式去实现。
使用建议
具体实现
静态代理(MVC模式就是一个典型的静态代理)
(静态代理实例一)老子帮儿子相亲:
类图:
代码:
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;
public interface Person {
void findLove();
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;
/**
* @program: demo-pom
* @description:
* @author: bo.hu
* @create: 2020-01-23 14:12
**/
public class Son implements Person{
@Override
public void findLove() {
System.out.println("不傻就行");
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;
/**
* @program: demo-pom
* @description: 代理对象类
* @author: bo.hu
* @create: 2020-01-23 14:13
**/
public class Father {
private Son son;
public Father(Son son) {
this.son = son;
}
public void findLove(){
System.out.println("父母角度出发:选择");
this.son.findLove();
System.out.println("双方父母同意交往,确立关系。");
}
public static void main(String[] args) {
Father f=new Father(new Son());
f.findLove();
}
}
(静态代理实例二)数据库的动态选择:
类图:
代码:
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;
import lombok.Data;
/**
* @program: demo-pom
* @description: 订单实体类
* @author: bo.hu
* @create: 2020-01-23 14:38
**/
@Data
public class Order {
private Object orderInfo;
private Long createTime;
private String id;
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;
/**
* @program: demo-pom
* @description:
* @author: bo.hu
* @create: 2020-01-23 14:44
**/
public class OrderMapper {
public int insert(Order order){
System.out.println("OrderMapper 创建 Order 成功");
return 1;
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;
public interface OrderService {
int createOrder(Order order);
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;
/**
* @program: demo-pom
* @description:
* @author: bo.hu
* @create: 2020-01-23 14:47
**/
public class OrderServiceImpl implements OrderService {
private OrderMapper orderMapper;
public OrderServiceImpl(OrderMapper orderMapper) {
this.orderMapper = orderMapper;
}
@Override
public int createOrder(Order order) {
System.out.println("OrderService 调用 orderMapper 创建订单");
return orderMapper.insert(order);
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;
import javax.xml.crypto.Data;
/**
* @program: demo-pom
* @description:
* @author: bo.hu
* @create: 2020-01-23 15:12
**/
public class DynamicDataSourceEntry {
public final static String DEFAULT = null;
private final static ThreadLocal<String> local = new ThreadLocal<>();
public DynamicDataSourceEntry() {
}
public static void clear() {
local.remove();
}
public static void get() {
local.get();
}
public static void restore() {
local.set(DEFAULT);
}
public static void set(String resource) {
local.set(resource);
}
public static void set(int year) {
local.set("DB_" + year);
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @program: demo-pom
* @description: 创建订单静态代理类
* @author: bo.hu
* @create: 2020-01-23 15:22
**/
public class CreateOrderProxy implements OrderService{
private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
private OrderService orderService;
public CreateOrderProxy(OrderService orderService) {
this.orderService = orderService;
}
public int createOrder(Order order){
before();
Long time = order.getCreateTime();
Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time)));
System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据。");
DynamicDataSourceEntry.set(dbRouter);
orderService.createOrder(order);
after();
return 0;
}
private void before() {
System.out.println("Proxy before method.");
}
private void after() {
System.out.println("Proxy after method.");
}
public static void main(String[] args) {
Order order=new Order();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Date date = null;
try {
date = sdf.parse("2017/02/01");
} catch (ParseException e) {
e.printStackTrace();
}
order.setCreateTime(date.getTime());
OrderService orderService = new CreateOrderProxy(new OrderServiceImpl(new OrderMapper()));
orderService.createOrder(order);
}
}
动态代理
JDK自带的动态代理
类图:
代码:
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;
public interface Person {
void findLove();
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_jdk;
import com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy.Person;
/**
* @program: demo-pom
* @description: 顾客
* @author: bo.hu
* @create: 2020-01-23 16:19
**/
public class Customer implements Person {
@Override
public void findLove() {
System.out.println("不傻就行");
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @program: demo-pom
* @description: 动态代理类java实现方式
* @author: bo.hu
* @create: 2020-01-23 16:09
**/
public class JDKMeipo implements InvocationHandler {
private Object target;
public Object getIntence(Object object){
this.target=object;
Class<?>clazz=target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj=method.invoke(this.target,args);
after();
return obj;
}
private void before() {
System.out.println("开始 物色人选");
}
private void after() {
System.out.println("结束 物色人选");
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_jdk;
import com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy.Person;
/**
* @program: demo-pom
* @description:
* @author: bo.hu
* @create: 2020-01-23 16:20
**/
public class Test {
public static void main(String[] args) {
// 动态代理类和被代理类必须继承同一个接口。
// 动态代理只能对接口中声明的方法进行代理。
// 每一个动态代理实例都有一个关联的InvocationHandler。
// 通过代理实例调用方法,方法调用请求会被转发给InvocationHandler的invoke方法。
// 只能代理声明在接口中的方法。
Person obj=(Person)new JDKMeipo().getIntence(new Customer());
obj.findLove();
}
}
CGLIB实现的动态代理(Spring中同时使用了JDK与CGLIB这两种代理)
类图:
代码:
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;
public interface Person {
void findLove();
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_cglib;
import com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy.Person;
public class Customer implements Person {
@Override
public void findLove() {
System.out.println("cglib findLove()");
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CgLibMeipo implements MethodInterceptor {
public Object getInstence(Class<?> clazz){
Enhancer enhancer =new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object obj=methodProxy.invokeSuper(o,objects);
after();
return obj;
}
private void after() {
System.out.println("代理类前置处理");
}
private void before() {
System.out.println("代理类后置处理");
}
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_cglib;
public class Test {
public static void main(String[] args) {
Customer customer=(Customer)new CgLibMeipo().getInstence(Customer.class);
customer.findLove();
}
}