设计模式原则22----观察者模式

个人博客:打开链接

一、定义

观察者模式属于对象的行为模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题(被观察者)对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

二、类图

这里写图片描述

三、观察者模式的结构

被观察者:从类图中可以看到,类中有一个用来存放观察者对象的Vector容器(之所以使用Vector而不使用List,是因为多线程操作时,Vector在是安全的,而List则是不安全的),这个Vector容器是被观察者类的核心,另外还有三个方法:attach方法是向这个容器中添加观察者对象;detach方法是从容器中移除观察者对象;notify方法是依次调用观察者对象的对应方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
观察者:观察者角色一般是一个接口,它只有一个update方法,在被观察者状态发生变化时,这个方法就会被触发调用。
具体的被观察者:使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑。
具体的观察者:观察者接口的具体实现,在这个角色中,将定义被观察者对象状态发生变化时所要处理的逻辑。

四、使用场景

一个对象的状态发生改变, 通知到某些与它相关的对象,让他们可以随之做出相应的变化
1、抽象主题类

//抽象主题类  
public abstract class Subject {  
    // 观察者集合  
    private List<Observer> list = new ArrayList<Observer>();  

    // 添加观察者  
    public void register(Observer observer) {  
        list.add(observer);  
    }  
    //删除  
    public void remove(Observer observer) {  
        if (list.contains(observer)) {  
            list.remove(observer);  
        }  
    }  

    public void change(String status) {  
        this.notifyObserver(status);  
    }  
    //通知所有观察者  
    private void notifyObserver(String status) {  
        for (Observer observer : list) {  
            observer.update(status);  
        }  
    }  
}  

2、主题具体实现类

//具体主题角色类  
public class RealSubject extends Subject {  

    private String status;  

    public String getStatus() {  
        return status;  
    }  

    public void setStatus(String status) {  
        this.status = status;  
    }  

    public void change(String status) {  
        System.out.println("当前主题状态:" + status);  
        super.change(status);  
    }  
}  

3、观察者接口

//观察者接口  
public interface Observer {  

    public void update(String status);  
}  

4、具体观察者接口实现

//具体观察者类  
public class RealObserver implements Observer {  

    private String name;  
    private String innerStatus;  

    public RealObserver(String name) {  
        super();  
        this.name = name;  
    }  

    @Override  
    public void update(String status) {  
        this.innerStatus = status;  
        System.out.println("观察者" + name + ",状态:" + innerStatus);  
    }  

    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        this.name = name;  
    }  
}  

5、客户端Client测试

public class Client {  

    public static void main(String[] args) {  
        // 创建主题  
        RealSubject subject = new RealSubject();  

        // 创建观察者  
        Observer observerA = new RealObserver("张三");  
        Observer observerB = new RealObserver("李四");  
        // 给主题添加观察者  
        subject.register(observerA);  
        subject.register(observerB);  

        // 改变主题内容状态  
        subject.change("start");  
    }  
}  

五、优点

 易扩展: 观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。

六、缺点

性能欠佳:如一个主题被大量观察者注册,则通知所有观察者会花费较高代价
容易阻塞: 如果某些观察者的响应方法被阻塞,整个通知过程即被阻塞,其它观察者不能及时被通知

猜你喜欢

转载自blog.csdn.net/jinglisen/article/details/80489072