设计模式-代理和观察者



提示:以下是本篇文章正文内容,下面案例可供参考

一、代理模式

1、概念

为其他东西提供代理以控制对对象的访问  ,  相对于一个中介
在有的时候一个对象不能或者不适合直接引另一个对象,而代理对象就可以成为中介的桥梁作用

2、特点

  1. 特征是代理类与委托类有同样的接口(有特别情况不一定),代理负责为委托类预处理信息过滤信息,把信息转发给委托类,以及处理信息等

  2. 代理类对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来通过特定的服务。

3、实现

  1. 静态代理
    银行雇员代理客户执行相关银行服务
/**
 * @author zhangyifan
 * @version 8.0
 * @description:委托类和代理类拥有的共同接口
 * @date 2021/12/3 9:58
 */
public interface Account {
    /**
     *y银行
     */
    void query();
    void cueng();
}

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 9:58
 */
public class Client implements Account {
    @Override
    public void query() {
        System.out.println("XXX  取了多少钱");
    }

    @Override
    public void cueng() {
        System.out.println("   查");
    }
}
/**
 * @author zhangyifan
 * @version 8.0
 * @description:    代理  银行顾元
 * @date 2021/12/3 9:59
 */
public class Employee implements Account{
    //委托
    private Client client;

    public Employee(Client client) {
        this.client = client;
    }

    /**
     * 通过构造 或者set 方法给 赋值
     */

    @Override
    public void query() {
        System.out.println("取钱钱干什么");
        client.query();
        System.out.println("取钱后干什么");
    }

    @Override
    public void cueng( ) {
        System.out.println("查询余额做什么准备");
        client.cueng( );
        System.out.println("查询后做什么工作");
    }
}
/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 14:32
 */
public class Testa {
    public static void main(String[] args) {
        Client client=new Client();
        Employee employee=new Employee(client);
        employee.cueng( );
        employee.query();
    }
}

  1. jdk动态代理

java.lang.reflect包下提共了一个Proxy类和一个invocationhandler接口 用来完成动态代理

Invocationhandler接口:
当我们通过代理对象调用一个方法时,这个方法的调用就会被转发为由Invocationhandler这个接口的invoke方法进行调用。

Object invoke(Object proxy,Method method ,Object[] args)

参数:Object proxy:指被代理的对象
Method method: 要调用的方法
Object[] args: 方法调用时所需的参数

Proxy类 :该类提供了一个创建动态代理对象的方法。
static Object newProxyInstance(ClassLoader loader,Class《?》【】 interface,Invocationhandler h)

ClassLoader loader:定义代理类的类加载器
Class《?》【】interface : 代理类要实现的接口列表
invocationHandler h:指派方法调用的调用处理程序 表示代理对象要关联的 invocationHandler对象。

/**
 * @author zhangyifan
 * @version 8.0
 * @description: JDK代理 可以代理任意委托类
 * @date 2021/12/3 10:42
 */
public class JDKProxy implements InvocationHandler {
    /**
     * 委托类
     */
    private Object obj;

    /**
     * 给委托类赋值,返回代理类对象
     * @param obj
     * @return
     */
    public Object bindObj(Object obj){
        this.obj=obj;
        //获取委托类的所有接口 通过方式
        Class<?>[] interfaces = this.obj.getClass().getInterfaces();
        //参数1 类加载器  参数2、
        return Proxy.newProxyInstance(
                JDKProxy.class.getClassLoader()
                ,interfaces
                  ,this);
    }
    /**
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result=null;
        String name=method.getName();
        System.out.println("方法名称为:"+name);
      /*  if ("query".equals(name)){
            System.out.println("存取前做什么准备。。。。。。");
            result = method.invoke(this.obj,args);
            System.out.println("存取后做什么工作。。。。。。");
        }else if ("cueng".equals(name)){
            System.out.println("查询前");
            result = method.invoke(this.obj,args);
            System.out.println("查询后");
        }*/
        System.out.println("前干什么");
        result =method.invoke(this.obj,args);
        System.out.println("后干什么");
        return result;

    }
}

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 15:22
 */
public interface DeptService {
    /**
     * 修改
     * @param o
     * @return
     */
    int update(Object o);

    /**
     * 添加
     * @param o
     * @return
     */
    int add(Object o);

    /**
     * 删除
     * @param id
     * @return
     */
    int deleteById(int id);

    /**
     * 分页带参数查询
     * @param str
     * @return
     */
    List<Object> queryAll(String ...str);
}
/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 15:23
 */
public class DeptServiceImpl implements DeptService{
    @Override
    public int update(Object o) {
        System.out.println("...............模拟更新。。。。。。。。。。。。。。。。。");
        return 0;
    }

    @Override
    public int add(Object o) {
        System.out.println("...............模拟添加。。。。。。。。。。。。。。。。。");
        return 0;
    }

    @Override
    public int deleteById(int id) {
        System.out.println("...............模拟删除。。。。。。。。。。。。。。。。。");
        return 0;
    }

    @Override
    public List<Object> queryAll(String... str) {
        System.out.println("...............模拟查询。。。。。。。。。。。。。。。。。");
        return null;
    }
}
/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 15:39
 */
public class TestA {
    public static void main(String[] args) {
        DeptService deptService=new DeptServiceImpl();

        JDKProxy jdkProxy=new JDKProxy();
        DeptService deptService1 = (DeptService) jdkProxy.bindObj(deptService);
        deptService1.add(1);
        deptService1.update(1);
        deptService1.deleteById(1);
        deptService1.queryAll();
    }
}

  1. CGLIB(Code Generation Library) 动态代理
    主要应用于没有接口的动态代理生成(主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的),Spring AOP 框架 ,HIbernate都使用了CGLLIB。
/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 16:56
 */
public class DeptServiceImpl implements DeptService {
    public final int update(Object o) {
        System.out.println("................模拟更新。。。");
        return 0;
    }

    public int add(Object o) {
        System.out.println("................模拟添加。。。");
        return 0;
    }

    public int deleteById(int id) {
        System.out.println("................模拟删除。。。");
        return 0;
    }

    public List<Object> queryAll(String... str) {
        System.out.println("................模拟查询。。。");
        return null;
    }
}

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 16:56
 */
public class CGLbProxy implements MethodInterceptor {

    //委托
    private Object obj;

    public Object binObj(Object obj){
        this.obj=obj;
        Enhancer enhancer=new Enhancer();
        //设置生成代理类的付类
        enhancer.setSuperclass(this.obj.getClass());
        //生成委托类的子类后 用Callback调用子类的所有方法
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result=null;
        System.out.println("事情前");
        result=methodProxy.invoke(this.obj,objects);
        System.out.println("事情后");
        return null;
    }
}

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 16:57
 */
public class Test {
    public static void main(String[] args) {
        DeptService deptService=new DeptServiceImpl();//实例
        CGLbProxy cgLbProxy=new CGLbProxy();//委托
        DeptService deptService1 = (DeptService) cgLbProxy.binObj(deptService);
        deptService.deleteById(1);
        System.out.println("==================");
        deptService1.deleteById(1);
    }
}

二、观察者模式(Observer Pattern)

1.定义

观察者模式是软件设计模式的一种。它定义了一种一对多的依赖关系,让多个观察者对象同时监听听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。在观察者模式中,监视另一个对象状态的对象称为Observer,正在被监视的对象称为Subject。

2.现实例子

例如,某种商品的物价上涨时会导致部分商家高兴,而消费者伤心;还有,当我们开车到交叉路口时,遇到红灯会停,遇到绿灯会行。这样的例子还有很多,例如,股票价格与股民、微信公众号与微信用户、气象局的天气预报与听众、小偷与警察等

3.角色

  1. 抽象主题(Subject)
    它把所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
  2. 具体主题(Concrete Subject)
    将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
  3. 抽象观察者(Observer)
    为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  4. 具体观察者(Concrete Observer)
    实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

被观察者接口

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 11:43
 */
public interface Subject {
    /**
     * 注册观察z
     */
    void registerObservier(ObServer obServer);

    /**
     * 移除
     * @param obServer
     */
    void removeObserver(ObServer obServer);
    /**   
     *  * 通知所有观察者 
     *   @param message   
     *  */
    void notifyObserver(String  message);
}

被观察者实现

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 11:45
 */
public class ConcreteSubject implements Subject{

    //观察者集合
    private List<ObServer> obServers=new ArrayList<>();

    @Override
    public void registerObservier(ObServer obServer) {
        obServers.add(obServer);
    }

    @Override
    public void removeObserver(ObServer obServer) {
        obServers.remove(obServer);
    }

    @Override
    public void notifyObserver(String message) {
        if (obServers!=null&&obServers.size()>0){
            for (ObServer observer:obServers){
                observer.update(message);
            }
        }
    }
}

观察者:

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 11:44
 */
public interface ObServer {
    /**根据主题变化,观察者也发生变化
     *
     * @param message
     */
    void update(String message);
}

观察者实现

/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 18:51
 */
public class ConcreteObserver implements ObServer {
    //观察者
    private String obName;
    public ConcreteObserver(String obName){
        this.obName=obName;
    }

    @Override
    public void update(String message) {
        System.out.println("观察者"+obName+"根据"+message+"变化,自己做了什么什么调整。。。。");
    }
}

测试

 /**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/3 18:54
 */
public class Test {
    public static void main(String[] args) {
        //实例化 OB
        ObServer obServer1=new ConcreteObserver("ob1");
        ObServer obServer2=new ConcreteObserver("ob2");
        ObServer obServer3=new ConcreteObserver("ob3");
        ObServer obServer4=new ConcreteObserver("ob4");
        //实例化
        Subject subject=new ConcreteSubject();
        subject.registerObservier(obServer1);
        subject.registerObservier(obServer2);
        subject.registerObservier(obServer3);
        subject.registerObservier(obServer4);
        //主题变化
        subject.notifyObserver("变黄了");
        System.out.println("-----------------------------");
        //移除
        subject.removeObserver(obServer1);//移除
        subject.notifyObserver("变红了");
/* org.example.dp.observer.Test
观察者ob1根据变黄了变化,自己做了什么什么调整。。。。
观察者ob2根据变黄了变化,自己做了什么什么调整。。。。
观察者ob3根据变黄了变化,自己做了什么什么调整。。。。
观察者ob4根据变黄了变化,自己做了什么什么调整。。。。
-----------------------------
观察者ob2根据变红了变化,自己做了什么什么调整。。。。
观察者ob3根据变红了变化,自己做了什么什么调整。。。。
观察者ob4根据变红了变化,自己做了什么什么调整。。。。*/
    }
}


4、好处

观察者模式将观察者和主题(被观察者)彻底解耦,主题只知道观察者实现了某一接口(也就是Observer接口)。并不需要观察者的具体类是谁、做了些什么或者其他任何细节。任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现了Observer接口的对象列表。

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Network porter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值