简单理解代理模式—静态代理
静态代理模式可以简单理解为 房东-中介-租客 的关系,我们按照下面的代码帮助理解:
// 定义一个接口
public interface UserDao {
void add();
void update();
void findByUserName();
}
// 实现上面的接口
import Dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("add方法被执行了.....");
}
@Override
public void update() {
System.out.println("update方法被执行了.....");
}
@Override
public void findByUserName() {
System.out.println("findByUserName方法被执行了.....");
}
}
上面的代码就可以理解为房东对这个房子租出去所要求的最基本要求
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
// 注意:这里也实现了UserDao接口
@SuppressWarnings("all")
public class UserDaoProxy implements UserDao {
private UserDaoImpl userDaoImpl = new UserDaoImpl();
private String logPath = "log.txt";
@Override
public void add() {
userDaoImpl.add();
try {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(logPath , true));
bufferedWriter.write(LocalDateTime.now() + " add被调用了......");
bufferedWriter.newLine();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void update() {
userDaoImpl.update();
try {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(logPath , true));
bufferedWriter.write(LocalDateTime.now() + " update被调用了......");
bufferedWriter.newLine();
bufferedWriter.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void findByUserName() {
userDaoImpl.findByUserName();
System.out.println("进入了静态代理模式");
try {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(logPath , true));
bufferedWriter.write(LocalDateTime.now() + " findByUserName被调用了......");
bufferedWriter.newLine();
bufferedWriter.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
上面的代码,就可以理解为中介,房东对房子的要求就是增加,修改,查找,但是中介这时候就说了:“我肯定满足房东的要求,但是我不能白干活啊,我要在你要求的基础上,我还要增加我自己的要求,赚点中介费”。这也是静态代理的目的,也就是在不修改原代码的情况下,增强原有功能,实现了零代码入侵。
可以看上面我的UserDaoProxy代码例子(需要注意的是,UserDaoProxy也需要实现UserDao接口):在重写其中的增加,修改,查找的原有方法后,我们调用UserDaoImpl 中的增加,修改,查找方法,并在调用的前后,可以加入我们希望执行的其他逻辑。比如我上面所写的,我希望这个方法被调用后,能被记录下来。这就实现了功能增强,因为在UserDaoImpl中,也就是房东,是没有要求要记录日志的,但是UserDaoProxy这个中介,就在其中增加了日志要求,并且我也满足了房东UserDaoImpl的增改查的功能,这就是静态代理。
public class UserDaoProxyFactory {
// 获取代理对象
public static UserDaoProxy getUserDaoProxy(){
return new UserDaoProxy();
}
}
上面的代码就是静态工厂,说白了就是通过这段代码,获得静态代理对象。
// 测试
import Dao.UserDao;
import Proxy.UserDaoProxyFactory;
public class Test {
public static void main(String[] args) {
UserDao userDao = UserDaoProxyFactory.getUserDaoProxy();
userDao.add();
userDao.update();
userDao.findByUserName();
}
}
成功增强原有功能。
但是,刚才你就可能注意到了一个问题:如果我只是想增强一个add功能,也就是只记录一个add方法被调用的日志,其他的方法我不想增强。但是由于UserDaoProxy实现了UserDao接口,所以UserDaoProxy又必须要重写所有的方法,那这是不是有点太累赘了?而且,当UserDao中新增了一个方法,那难道所有的代理类都要去实现这个多出的方法吗?
上面的问题就是静态代理模式的缺点:
- 代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
- 如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
动态代理模式就完美解决了上面的问题。
我会再出一篇文章,尽可能简单地描述动态代理模式。
如果这篇代理模式—静态代理的文章有什么错误或不足,也希望各位大佬指正