上一节说到装饰器模式: https://blog.csdn.net/zhanglei082319/article/details/88592661
装饰器模式概念:为一个业务实现,添加该业务内一些其他的职责,称之为装饰器模式。
今天说另一种设计模式:代理模式
代理模式: 生活中的中介,中间商等等都是代理,java中的代理的概念也差不多。代理者拥有委托人的部分权限,代理者也可以在代理的同时加上自己的部分业务。
java中代理模式分为两种:静态代理和动态代理。
静态代理:在程序启动前将接口,实现类,代理类全部手动实现完成。就手机销售代理商问题的静态代理实现如下:
1、先定义一个商家接口
/**
* 商家
*/
public interface Business {
/**
* 零售
*/
void retail();
/**
* 批发
*/
void wholesale();
}
2、定义一个苹果手机商家实现类
/**
* 苹果商家
*/
public class IPhoneBusiness implements Business {
@Override
public void retail() {
System.out.println("成功卖出一个苹果手机!");
}
@Override
public void wholesale() {
System.out.println("成功卖出多台苹果手机!");
}
}
3、定义静态代理实现类
/**
* 代理商家
*/
public class ProxyBusiness {
private Business business = new IPhoneBusiness();
public void sell(){
System.out.println("代理销售!");
business.retail();
}
}
4、测试一下静态代理
public static void main(String[] args) {
ProxyBusiness proxyBusiness = new ProxyBusiness();
proxyBusiness.sell();
}
打印结果测试完成,代理商成功销售出一台手机。
从接口实现中可以看到,目前代理商能够销售苹果手机。
我们假设代理商在销售苹果手机时,需要在商品包装上需要贴上自己的独家代理商标签。随着代理商业务逐渐扩大,我们的代理商需要代理很多种款式的手机,而且每一种款式的手机都需要贴上自己的标签。
这种情况下,如果还是继续使用静态代理的方式进行,那么不可避免的会存在很多冗余的功能代码实现。我们希望将这些统一的功能可以放在一个地方实现。怎么办呢?
动态代理: 运行时生成的代理实现类和实例,我们称之为动态代理。
使用动态代理实现多种手机代理商贴标签的功能如下:
1、为了实现多个款式的手机,这里添加一个手机代理商
/**
* 华为手机
*/
public class HuaweiPhoneBusiness implements Business{
@Override
public void retail() {
System.out.println("成功销售一台华为手机");
}
@Override
public void wholesale() {
System.out.println("成功销售多台华为手机");
}
@Override
public String name() {
return "华为手机";
}
}
2、动态代理商实例创建器
public class ProxyFactory {
private static void before(Business business){
System.out.println(business.name()+": 贴上代理商标签");
}
private static void after(Business business){
System.out.println(business.name()+": 销售成功");
}
private static Business getProxy(Business business) {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(business);
method.invoke(business, args);
after(business);
return null;
}
};
return (Business) Proxy.newProxyInstance(Business.class.getClassLoader(),
new Class[]{Business.class}, handler);
}
}
测试一下
public static void main(String[] args) {
Business iphone = ProxyFactory.getProxy(new IPhoneBusiness());
Business huawei = ProxyFactory.getProxy(new HuaweiPhoneBusiness());
iphone.retail();
iphone.wholesale();
huawei.retail();
huawei.wholesale();
}
这样我们就可以将贴标签这个业务功能,单独放在一个地方进行实现了,当然只要是一些公共的功能我们都可以放置在统一的地方实现。在实例化代理商的时候,判断这个代理商是否有公共的功能需要实现,如果有就实例化代理对象,如果没有就普通实例化自身。
代理模式的使用场景
静态代理模式: 一般在一个类,针对于不同的调用者会赋予不同的权限时,我们可以使用静态代理模式。还有当我们需要对一个类进行某些功能的修改,但是又不能直接去内部修改,这时可以使用静态代理。
动态代理模式: 这个一般比较侧重于方法上,当一个方法执行前后或者中间需要使用到一些公共的功能,可以使用动态代理。 还有jdk动态代理是面向接口的,当遇到一些固定的只需要定义接口,不许要实现类的情况,我们可以动态代理生成固定功能的实现类。
实际项目中代理模式使用也非常频繁,特别是动态代理,我们熟知的springAop mybatis中的mapper connection log 等等都使用了动态代理。