设计模式_10:观察者模式

观察者(Observer)模式又称为发布订阅模式(Publish/Subscribe),如果一个对象改变时需要通知其他对象,那么就可以用观察者模式解决。

一个简单的例子:顾客订阅了卖家,以后卖家有什么新消息(优惠活动、打折什么的)就可以找到并通知给顾客了:

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        Seller seller = new Seller();
        Customer tony = new Customer("Tony", seller);
        Customer lisa = new Customer("Lisa", seller);
        seller.attach(tony);
        seller.attach(lisa);
        seller.setNotifyText("薯条、薯片半价");
        seller.send_notify();
    }
}

//卖家(消息通知者)
class Seller {

    private String notifyText;
    private List<Customer> customerList = new ArrayList<>();

    //添加顾客(消息订阅者)
    public void attach(Customer customer){
        customerList.add(customer);
    }

    //通知顾客最新消息
    public void send_notify(){
        for (Customer customer : customerList){
            customer.update();
        }
    }

    public String getNotifyText() {
        return notifyText;
    }

    public void setNotifyText(String notifyText) {
        this.notifyText = notifyText;
    }
}

//顾客(消息订阅者)
class Customer {

    private String name;
    private Seller seller;

    public Customer(String name, Seller seller) {
        this.name = name;
        this.seller = seller;
    }

    //得到通知时所采取的行动(这里只是简单地输出一下通知内容)
    public void update(){
        System.out.println(name + "收到通知:" + seller.getNotifyText());
    }

}


运行结果:

Tony收到通知:薯条、薯片半价
Lisa收到通知:薯条、薯片半价


基本的观察者模式是这样了,不过现在卖家和顾客相互紧紧的耦合在一起了,也就是说顾客依赖于具体的卖家,卖家也需要知道具体的顾客,不符合依赖倒转原则,并且如果老板(另一种订阅者)也需要订阅卖家的消息,那么原来卖家的代码就需要修改了,这样也不符合开放-闭合原则,所以需要改良 解耦:

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        Seller seller = new Seller();
        Customer tony = new Customer("Tony", seller);
        Customer lisa = new Customer("Lisa", seller);
        seller.attach(tony);
        seller.attach(lisa);
        seller.setNotifyText("薯条、薯片半价");
        seller.send_notify();
    }
}

//卖家(消息通知者)
class Seller {

    private String notifyText;
    //把Customer改成Observer
    private List<Observer> observerList = new ArrayList<>();

    //添加顾客(消息订阅者)
    public void attach(Observer observer){
        observerList.add(observer);
    }

    //去除顾客(以后不再通知该顾客)
    public void detach(Observer observer){
        observerList.remove(observer);
    }

    //通知顾客最新消息
    public void send_notify(){
        for (Observer observer : observerList){
            observer.update();
        }
    }

    public String getNotifyText() {
        return notifyText;
    }

    public void setNotifyText(String notifyText) {
        this.notifyText = notifyText;
    }
}

//抽象出一个观察者类(抽象消息订阅者)
abstract class Observer {

    protected String name;
    protected Seller seller;

    public Observer(String name, Seller seller) {
        this.name = name;
        this.seller = seller;
    }

    abstract void update();

}

//顾客(具体消息订阅者)
class Customer extends Observer{

    public Customer(String name, Seller seller) {
        super(name, seller);
    }

    //得到通知时所采取的行动(这里只是简单地输出一下通知内容)
    @Override
    public void update(){
        System.out.println(name + "收到通知:" + seller.getNotifyText());
    }

}

通过依赖抽象类Observer,Seller类就不需要知道具体订阅消息的是谁了,但现在顾客依赖的仍然是具体的卖家,所以还需要改改:

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        Subject seller = new Seller();
        Observer tony = new Customer("Tony", seller);
        Observer lisa = new Customer("Lisa", seller);
        seller.attach(tony);
        seller.attach(lisa);
        seller.setSubjectState("薯条、薯片半价");
        seller.send_notify();
    }
}

//把消息发布者抽象成接口
interface Subject {

    void attach(Observer observer);
    void detach(Observer observer);
    void send_notify();

    String getSubjectState();
    void setSubjectState(String subjectState);

}

//卖家(消息通知者)
class Seller implements Subject{

    private String notifyText;
    //把Customer改成Observer
    private List<Observer> observerList = new ArrayList<>();

    //添加顾客(消息订阅者)
    @Override
    public void attach(Observer observer){
        observerList.add(observer);
    }

    //去除顾客(以后不再通知该顾客)
    @Override
    public void detach(Observer observer){
        observerList.remove(observer);
    }

    //通知顾客最新消息
    @Override
    public void send_notify(){
        for (Observer observer : observerList){
            observer.update();
        }
    }

    @Override
    public String getSubjectState() {
        return this.notifyText;
    }

    @Override
    public void setSubjectState(String subjectState) {
        this.notifyText = subjectState;
    }
}

//抽象出一个观察者类(抽象消息订阅者)
abstract class Observer {

    protected String name;
    protected Subject subject;

    public Observer(String name, Subject subject) {
        this.name = name;
        this.subject = subject;
    }

    abstract void update();

}

//顾客(具体消息订阅者)
class Customer extends Observer{

    public Customer(String name, Subject subject) {
        super(name, subject);
    }

    //得到通知时所采取的行动(这里只是简单地输出一下通知内容)
    @Override
    public void update(){
        System.out.println(name + "收到通知:" + subject.getSubjectState());
    }

}

最后,我把消息发布者也抽象成接口了



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值