观察者模式

什么是观察者模式?

​ 指多个对象存在一对多的依赖关系,当一个对象(观察者)那个发生改变时,所有依赖于他的对象(目标)都得到通知并被自动更新。这种模式又称为 发布-订阅模式、模型-视图模式,他是对象行为型模式

优点?
  • 降低了目标与观察者之间的耦合关系。符合依赖倒置原则
  • 当观察者对象过多时,通知的发布会花费很多时间

先看一个小demo:

​ 报社 :有生产 报 的方法

​ 读者 :有读报 的方法 有三类读者

​ 报 : domain

分析累与类的关系:

​ 报社 与 报:生产报

​ 报社 与 读者: 读者 读 去报社生产的报(依赖关系)

  • 代码如下:

    • Paper

      package javas.observer;
      
      public class Paper {
          private String name;
      
          public Paper(String name) {
              this.name = name;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      
    • Public

      package javas.observer;
      
      public class Public {
          private String name;
      
          public Public(String name) {
              this.name = name;
          }
      
          public Paper generatePaper(){
              return new Paper("人民日报");
          }
      
          public String getName() {
              return name;
          }
      }
      
      
      
    • Reader

      package javas.observer;
      
      public interface Reader {
          void read(Public p);
      }
      
    • ReadOne

      package javas.observer;
      
      public class ReadOne implements Reader{
          private String name;
          public ReadOne(String name) {
              this.name = name;
          }
          public void read(Public p){
              System.out.println(this.name+" 读了 "+p.getName()+" 的 "+p.generatePaper().getName()+" 报纸");
          }
      }
      
    • ReadTwo

      package javas.observer;
      
      public class ReadTwo implements Reader{
          private String name;
      
          public ReadTwo(String name) {
              this.name = name;
          }
      
          public void read(Public p){
              System.out.println(this.name+" 读了 "+p.getName()+" 的 "+p.generatePaper().getName()+" 报纸");
          }
      }
      
    • ReadThree

      package javas.observer;
      
      public class ReadThree implements Reader{
          private String name;
      
          public ReadThree(String name) {
              this.name = name;
          }
      
          public void read(Public p){
              System.out.println(this.name+" 读了 "+p.getName()+" 的 "+p.generatePaper().getName()+" 报纸");
          }
      }
      
    • Test

      package javas.observer;
      
      public class Test {
          public static void main(String[] args) {
              Public p = new Public("新华日报");
              Reader ro = new ReadOne("张三");
              Reader rt = new ReadTwo("李四");
              Reader rh = new ReadThree("王五");
      
              ro.read(p);
              rt.read(p);
              rh.read(p);
          }
      }
      

    两个问题:

    • 创建读者对象方式太麻烦:解决方法 使用反射 ioc(对象控制权反转) di(依赖注入)

    • 每个读者对象都需要主动做事:

      • 观察者设计模式: 一个对象和一堆对象的关系 (一个对象做事情 一堆对象自动做事情)

      • 观察者: 报社

      • 目标对象:读者

        ​ 只要报社出版了报纸就让读者读报纸

  • 改进

    • 反射

      package javas.observer;
      
      import java.lang.reflect.Constructor;
      import java.lang.reflect.Field;
      import java.lang.reflect.Method;
      import java.util.Scanner;
      
      public class MySpring {
          public static Object getInstance(String className) {
              Object obj = null;
              Scanner scanner = new Scanner(System.in);
              try {
                  Class aClass = Class.forName(className);
      // 控制权反转
                  Constructor con = aClass.getDeclaredConstructor();
                  obj = con.newInstance();
      // 依赖注入:获取set方法
                  Field[] fields = aClass.getDeclaredFields();
                  for (int i = 0; i < fields.length; i++) {
                      // 获取其类型
                      Class fieldType = fields[i].getType();
                      // 获取其属性名
                      String fileName = fields[i].getName();
                      // 拼接 setName 方法
                      StringBuilder setMethod = new StringBuilder("set");
                      String first = fileName.substring(0, 1).toUpperCase();
                      String other = fileName.substring(1);
                      setMethod.append(first);
                      setMethod.append(other);
                      // 获取set方法
                      Method method = aClass.getDeclaredMethod(String.valueOf(setMethod), fieldType);
                      //
                      // 八个基本类型的包装类中 只有char类型没有带String参数的方法
                      Constructor typeCon = fieldType.getDeclaredConstructor(String.class);
                      System.out.println("请输入"+fileName);
                      String s = scanner.nextLine();
                      method.invoke(obj,typeCon.newInstance(s));
      
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return obj;
      
      
          }
      }
      
    • Public

      package javas.observer;
      
      import java.util.ArrayList;
      
      public class Public {
          private String name;
          public Public(String name) {
              this.name = name;
          }
          public Paper generatePaper(){
              return new Paper("人民日报");
          }
      
          public String getName() {
              return name;
          }
          // 反转类与类的设计模式:变为 has a的关系
          private ArrayList<Reader> readers = new ArrayList<>();
          public void addReader(Reader reader){
              readers.add(reader);
          }
          public void removeReader(Reader reader){
              readers.remove(reader);
          }
          public void sendInfoToReader(){
              for (int i = 0; i < readers.size(); i++) {
                  this.readers.get(i).read(this);
              }
          }
      
      
      
      }
      
    • Test

      package javas.observer;
      
      public class Test {
          public static void main(String[] args) {
              Public p = new Public("新华日报");
              // 反射技术
              ReadOne ro = (ReadOne)MySpring.getInstance("javas.observer.ReadOne");
              ReadTwo rt = (ReadTwo) MySpring.getInstance("javas.observer.ReadTwo");
              ReadThree rh = (ReadThree) MySpring.getInstance("javas.observer.ReadThree");
      
              p.addReader(ro);
              p.addReader(rt);
              p.addReader(rh);
      
              p.sendInfoToReader();
          }
      }
      
    • 其他不变

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值