代理模式:
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口
代理模式在java中是很重要的一个知识点,并且在实际开发中经常会用到代理模式的知识,代理模式有两种形式,分别是静态代理和动态代理,此篇文章主要介绍静态代理的实现
静态代理:
在实际开发中我们已经完成了一个方法,这个方法完成一个独立的功能,但是在后期对于这个功能模块因为用户增加类需求,现在需要将扩展该方法的功能,因为此时产品已经上线,所以这个时候不可以动源代码,于是就产生出了代理这一思想,即在不动源代码的情况下,对方法的功能做出扩展.
那么怎么实现呢?因为java的一大核心思想就是面向接口编程(这就是java的魅力)因为面向接口编程大大提高了程序的可扩展性,回归正题,要实现静态代理,我们可以重新写一个类,这个类继承原有业务类的父类,然后将新的功能写到这个类中,于是我们使用的时候可以由父类对象调用静态代理类重写的方法,这样就实现了在不懂源代码的前提下,对功能做出了扩展.我将这一思想理解为物理学中的短路.
下面我就以一个插入业务为例从代码层次来说明:
- 这是原有业务类,实现了增加用户的功能
public class UserServiceImpl implements UserService {
private UserDao userDao=new UserDaoImpl();
@Override
public boolean addUser(User user) {
System.out.println("UserServiceImpl.addUser()");
int rowAffect=userDao.addUser(user);
return false;
}
}
- 此类是一个新的功能类 目的是要把这个新的功能类添加到原有的业务上
public class TransactionManager {
public void begin() {
System.out.println("事务开启!");
}
public void commit() {
System.out.println("事务提交!");
}
public void rollback() {
System.out.println("事务回滚!");
}
}
- 静态代理类
- 通过静态代理类把原有的业务和新功能的业务,必须耦合在一起
- 静态代理类必须实现业务的接口,因为静态代理类功能要跟业务一致
- 即静态代理类的功能不能少于原有业务
- 这里是使用spring框架做的对象注入,不过不妨碍阅读
package com.lxk.proxy;
public class StaticProxy implements UserService{
//组合耦合两个对象,业务对象,新功能对象
private UserService UserService;
private TransactionManager transactionManager;
public UserService getUserService() {
return UserService;
}
public void setUserService(UserService userService) {
UserService = userService;
}
public TransactionManager getTransactionManager() {
return transactionManager;
}
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Override
public boolean addUser(User user) {
boolean flag=false;
try {
transactionManager.begin();
UserService.addUser(user);
transactionManager.commit();
}catch (Exception e) {
transactionManager.rollback();
}
return flag;
}
}
下面是一个测试方法:
@Test
public void testMenthod2() {
//原有业务对象
UserService userService=new UserServiceImpl();
//新的功能业务对象
TransactionManager tm=new TransactionManager();
//静态代理类对象
StaticProxy sp=new StaticProxy();
sp.setUserService(userService);
sp.setTransactionManager(tm);
//通过静态代理对象调用业务方法来完成,原有业务和新业务的耦合
sp.updateUser(new User());
sp.addUser(new User());
}
输出的结果是:
事务开启!
UserServiceImpl.addUser()
UserDaoImpl.addUser()
事务提交!
由此可见成功了!
下面就来总结一下静态代理的特点:
1.没有修改原有的业务代码,没有破坏开闭原则
2.有新功能业务,且新功能业务类和原有业务类都独立的,遵守单一职责
3.新建了一个静态代理类,把原有的业务和新功能的业务耦合在一起
a.要求静态代理类要实现业务接口,保证业务完整性
b.有多少个业务,就有多少个静态代理类
比如:
UserService 对应 StaticProxy implements UserService
ProductService 对应 StaticProxy1 implements ProductService
…
典型从一个代码泥潭有调到另一个代码的泥潭(增加了静态代理类的代码量)
代码的泥潭:
UserServiceImpl.java --> StaticProxy.java
c.静态代理类不满足单一职责,在静态代理类中明显耦合了
原有业务和新功能业务
d.StaticProxy是静态代理类,此类的对象是代理对象
有多少个代理类,就会产生多少个代理对象,甚至更多个代理对象
e.静态代理类在编译期间就已经确认原有业务和新功能业务的耦合模型
由此可见静态代理虽然实现了我们的需求但是他最大的问题就是违反了单一职责,所以在实际开发中是不会使用这种方法的,在实际开发中使用的都是动态代理,动态代理我将在java动态代理详解和cglib动态代理做详细的讲解