设计模式 观察者模式

观察者模式也仍然是一种组件协作模式。

使用动机


可以具体一点,比如银行账户发生变化时,会自动发短信通知。steam玩游戏达到某一个条件时弹成就。
这种有一个“观察者”去时时刻刻的观察某一个东西的变化就可以使用观察者模式。

简单例子

假设银行账户金额发生变化,此时需要短信和邮箱通知
客户类

public class CustomerBank1 {
    private String email;
    private String phone;

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void notifyEmail(double amt){
        System.out.println("账号金额变动 发送邮件到"+email+"当前金额为"+amt);
    }
    public void notifyPhone(double amt){
        System.out.println("账号金额变动 发送短信到"+phone+"当前金额为"+amt);
    }
}

银行类:

public class BankAcount {
    private String name;
    private double amt;

    public String getName() {
        return name;
    }

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

    public double getAmt() {
        return amt;
    }

    public void setAmt(double amt) {
        this.amt = amt;
        CustomerBank1 customerBank1=new CustomerBank1();
        customerBank1.setEmail("***@***.com");
        customerBank1.notifyEmail(amt);
        customerBank1.setPhone("123456789");
        customerBank1.notifyPhone(amt);
    }
}

客户端:

public class Client {
    public static void main(String[] args) {
        BankAcount bankAcount=new BankAcount();
        bankAcount.setAmt(1000);
    }
}

不难看出我们的程序有一个问题,如果后续要新添加其他的通讯方式。那么客户类和银行类都必须去修改

这里不同的观察方式就是观察者(根据数据变化产生某一种行为),银行账户就是被观察类。

采用观察者模式优化

定义一个银行账户观察者接口

public interface BankObserver {
    public void update(double amt);
}

实现邮箱方式

public class CustomerBank1_Ob implements BankObserver {
    private String email;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public void update(double amt) {
        System.out.println("账号金额变动 发送邮件到"+email+"当前金额为"+amt);
    }
}

实现手机方式

public class CustomerBank2_OB implements BankObserver {
    private String phone;

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public void update(double amt) {
        System.out.println("账号金额变动 发送短信到"+phone+"当前金额为"+amt);
    }
}

银行账户类(被观察者)

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

public class BankAcount_OB {
    private String name;
    private double amt;
    List<BankObserver> list=new ArrayList<>();

    public String getName() {
        return name;
    }

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

    public double getAmt() {
        return amt;
    }

    //添加观察者
    public void add(BankObserver bankObserver){
        list.add(bankObserver);
    }
    private void remove(BankObserver bankObserver){
        list.remove(bankObserver);
    }
    public void notifyAmt(){
        for(int i=0;i<list.size();i++){
            BankObserver bankObserver=(BankObserver)list.get(i);
            bankObserver.update(amt);
        }
    }
    public void setAmt(double amt) {
        this.amt = amt;
        notifyAmt();
    }


}

客户端代码

public class Client_OB {
    public static void main(String[] args) {
        BankAcount_OB bankAcount_ob=new BankAcount_OB();
        CustomerBank1_Ob customerBank1_ob=new CustomerBank1_Ob();
        customerBank1_ob.setEmail("***@***.com");
        CustomerBank2_OB customerBank2_ob=new CustomerBank2_OB();
        customerBank2_ob.setPhone("123456789");
        bankAcount_ob.add(customerBank1_ob);
        bankAcount_ob.add(customerBank2_ob);
        //将1 2添加到观察者名单
        bankAcount_ob.setAmt(1000);
        //触发更新时所有观察者名单的update都被执行
    }
}

假设我们后续要添加QQ通知功能,就很方便了。只需要定义一个类去实现接口,之前写的代码无需修改

总结

posted @ 2021-03-21 10:05  一个经常掉线的人  阅读(50)  评论(0)    收藏  举报