观察者模式概念与java实现

现在想想,将以前学的一些设计模式搬运到CSDN上来吧,做个备注,防止遗忘。

(1)观察者模式的定义:

指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

  1. 模式的优缺点:

优点:

1、降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。

2、目标与观察者之间建立了一套触发机制。

缺点:

1、目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。

2、当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

(3)模式的结构图如图1所示。

 

图1 观察者模式结构图

(4)模式结构

1、抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

2、具体主题(Concrete    Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。

3、抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。

4、具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

图2 数据视图观察者模式实例图

 

1、Table类是抽象主题角色:提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

2、User类是具体主题角色:实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。

3、observer类是抽象观察者角色:是一个接口,包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。

4、observer1类和observer2类是具体观察者角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

 

User类中包含姓名,学号,性别,年龄,成绩等列。

视图1是observer1类,包含姓名、学号、成绩三列。

视图2是observer2类,包含姓名、成绩两列。

更新User类中数据时,两视图也应该作出相应的更新操作。

更新学号,视图1变化,视图2不变化,结果如图3所示。

 

图3 观察者模式结果-1

更新姓名,视图1变化,视图2也变化,结果如图3所示。

 

图4 观察者模式结果-2

 

 

1.观察者模式主要适用于以下情况:

①当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

②当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变。

③当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,不希望这些对象是紧密耦合的。

 

2. 观察者模式的优缺点:

观察者模式的主要的作用就是给对象解耦,将观察者和被观察者完全隔离。

①优点

观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。

②缺点

在应用观察者模式时需要考虑一下开发小路问题,程序中包括一个被观察者和多个被观察者,开发和调试比较复杂,而且Java中的消息的通知默认是顺序执行的,一个观察者的卡顿会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。

观察者:Observer接口
package Observer;

public interface observer {
    void response(String str,int i,String to);
}
观察者1:
package Observer;

public class observer1 implements observer{
    String[][] users = {
            {"姓名","学号","成绩"},
            {"小A","1704010101","80"},
            {"小B","1704010102","100"},
            {"小C","1704010103","90"},
            {"小D","1704010104","99"},
            {"小E","1704010105","70"}
    };

    @Override
    public void response(String str, int i, String to) {
        int flag=0;
        for(int j=0;j<3;j++){
            if(users[0][j].equals(str)==true){
                System.out.println("观察者1已更新!");
                users[i][j]=to;
                flag=1;
            }
        }
        if(flag==0){
            System.out.println("观察者1视图无需更新");
        }
        for(int k=0;k<6;k++){
            for(int j=0;j<3;j++){
                System.out.printf("%8s\t",users[k][j]);
            }
            System.out.println();
        }
    }

}

观察者2:

package Observer;

public class observer2 implements observer {
    String[][] users = {
            {"姓名","成绩"},
            {"小A","80"},
            {"小B","100"},
            {"小C","90"},
            {"小D","99"},
            {"小E","70"}
    };
    @Override
    public void response(String str, int i, String to) {
        int flag=0;
        for(int j=0;j<2;j++){
            if(users[0][j].equals(str)==true){
                System.out.println("观察者2已更新!");
                users[i][j]=to;
                flag=1;
            }
        }
        if(flag==0){
            System.out.println("观察者2视图无需更新");
        }
        for(int k=0;k<6;k++){
            for(int j=0;j<2;j++){
                System.out.printf("%8s\t",users[k][j]);
            }
            System.out.println();
        }
    }
}

抽象被观察者:

package Observer;

import java.util.ArrayList;

abstract public class table {
    protected ArrayList observers = new ArrayList();

    public void push(observer o){
        observers.add(o);
    }

    public void remove(observer o){
        observers.remove(o);
    }

    public abstract void modify(int i,int j,String to);
}

具体被观察者:

package Observer;

public class User extends table {
    String[][] users = {
            {"姓名","学号","性别","年龄","成绩"},
            {"小A","1704010101","男","22","80"},
            {"小B","1704010102","男","19","100"},
            {"小C","1704010103","男","20","90"},
            {"小D","1704010104","男","20","99"},
            {"小E","1704010105","男","20","70"}
    };
    public User(){
        for (int i=0;i<6;i++){
            for(int j=0;j<5;j++){
                System.out.printf("%8s\t",users[i][j]);
            }
            System.out.println();
        }
    }
    @Override
    public void modify(int i,int j,String to) {
        String str1 = users[0][j];
        for (Object obs:observers){
            ((observer)obs).response(users[0][j],i,to);
        }
    }
}

客户端(测试):

package Observer;

import java.util.Scanner;

public class client {
    public static void main(String[] args) {
        table A711 = new User();
        observer obs1 = new observer1();
        observer obs2 = new observer2();

        A711.push(obs1);
        A711.push(obs2);
        Scanner cin = new Scanner(System.in);

        System.out.println("请输入你要更改的坐标i:1-5 j:0-4 以及你想修改的值:");
        while(cin.hasNext()){
            int i=cin.nextInt();
            int j=cin.nextInt();
            String str = cin.next();
            A711.modify(i,j,str);
            System.out.println("请输入你要更改的坐标i:0-4 j:1-5 以及你想修改的值:");
        }
    }
}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值