每天一个设计模式 - 代理模式

代理模式的核心,是在被调用方和调用方之间增加一个中介者的角色,即代理
调用方 ===> 代理 ===> 被调用方
我们实际生活的情况,比如
  1. 租房中介,租客 ===> 中介 ===> 房东
  2. 抢票的黄牛,购票 ===> 黄牛 ===> 官方售票
  3. 菜鸟驿站,购物者 ===> 菜鸟驿站 ===> 快递小哥

编码上的体现:
现在我们有一个用户管理类,其中有添加用户、删除用户两个方法

public interface IUserService {

    /**
     * 添加用户
     */
    void insert();

    /**
     * 删除用户
     */
    void delete();
}
// 实现类
public class UserService implements IUserService{
    @Override
    public void insert() {
        // 添加用户
        System.out.println("执行添加用户......");
    }

    @Override
    public void delete() {
        // 删除用户
        System.out.println("执行删除用户......");
    }
}

假如我们需要在方法前后加打印日志的操作呢?
立马就有了解决方案,在方法前后加上打印日志的操作不就行了

public class UserService implements IUserService{
    @Override
    public void insert() {
    	System.out.println("添加用户前^_^");
        // 添加用户
        System.out.println("执行添加用户......");
        System.out.println("添加用户后o_o");
    }

    @Override
    public void delete() {
    	System.out.println("删除用户前^_^");
        // 删除用户
        System.out.println("执行删除用户");
        System.out.println("删除用户后o_o");
    }
}

之后,我们又有了新的需求,要加一个事务,或者加一个其他的前置功能呢?
再去修改代码,那么就会降低代码的可读性…
那么这时就有了代理类的登场

public class UserServiceStaticProxy implements IUserService{
    private final IUserService userService;

    public UserServiceStaticProxy(IUserService userService){
        this.userService = userService;
    }

    @Override
    public void insert() {
        System.out.println("添加用户开始......");
        userService.insert();
        System.out.println("添加用户结束......");
    }

    @Override
    public void delete() {
        System.out.println("删除用户开始......");
        userService.delete();
        System.out.println("删除用户结束......");
    }
}

代码中,代理类和业务类实现了相同的接口,并且重写了添加、删除用户的方法
在重写的代码中,我们就可以再去额外的操作处理了

public class ProxyClient {
    public static void main(String[] args) {
		IUserService userService = new UserServiceStaticProxy(new UserService());
        userService.insert();
        System.out.println();
        System.out.println("华丽的分割线---------->");
        System.out.println();
        userService.delete();
    }
}

执行结果返回

添加用户开始…
执行添加用户…
添加用户结束…
华丽的分割线---------->
删除用户开始…
执行删除用户
删除用户结束…

给对象的行为增加辅助功能的解决方案,就是代理模式

这时,我们再有其他的学生管理类、教师管理类需要增加日志,难道都要配置一个代理类吗???

根据上面代理类的命名也可以看出,上面进行的是一个静态代理,与之对应的还有一个动态代理
所谓动态代理,就是在程序运行时,动态的为被代理对象生成代理类,这就需要借助反射的特性了
这就需要使用到了InvocationHandler接口的实现和Proxy

public class UserServiceDynamicProxy implements InvocationHandler {

    private final IUserService userService;

    public UserServiceDynamicProxy(IUserService userService){
        this.userService = userService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName() + "方法调用前......");
        method.invoke(userService, args);
        System.out.println(method.getName() + "方法调用后......");
        return null;
    }
}
public class ProxyClient {
    public static void main(String[] args) {
        IUserService userService = new UserService();
        InvocationHandler userServiceInvocationHandler = new UserServiceDynamicProxy(userService);
        IUserService userServiceProxy = (IUserService) Proxy.newProxyInstance(userServiceInvocationHandler.getClass().getClassLoader(), userService.getClass().getInterfaces(), userServiceInvocationHandler);
        userServiceProxy.insert();

        System.out.println();

        userServiceProxy.delete();
    }
}

除了JDK的动态代理,还有CGlib的动态代理

那么,代理模式和装饰模式都是把原有的类对象作为成员,放在代理类或者装饰类中去调用,它们有什么区别呢???
从两个方向去区别

对于原有的类来说,装饰模式是“自己人”,是对自身功能的增加;而代理模式是“外人”,增加的功能和自身并无直接关系
另一个方向,代理模式关心的不是结果,是过程;装饰模式关心的是最终的结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我会尽力回答你的问题!今天我来为你介绍一种常见的Java设计模式:单例模式(Singleton Pattern)。 单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供一个全局访问点。在Java中,实现单例模式的方法有很多种,其中比较常见的一种是懒汉式单例模式。 懒汉式单例模式是指在第一次调用getInstance()方法时才会实例化对象。具体实现方法如下: ``` public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } ``` 在这个实现中,私有的构造函数保证了该类不能被外部实例化,而静态的getInstance()方法则提供了全局访问点。在getInstance()方法中,通过检查instance是否为null来实现懒加载。 需要注意的是,这种实现方式在多线程环境下存在线程安全问题,因此需要在getInstance()方法上加锁。当然,这也导致了性能上的一些损失。 除了懒汉式单例模式,还有饿汉式单例模式、双重检验锁单例模式、静态内部类单例模式等多种实现方式。不同的实现方式在性能、线程安全等方面各有优劣,需要根据具体的业务场景选择合适的实现方式。 希望这个简单的例子能帮助你更好地理解单例模式。如果你有任何问题或者需要进一步的解释,请随时告诉我!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值