针对这个设计模式,模拟一个场景来说明,首先是不使用观察者模式的一段代码,就拿干洗店洗衣服-取衣服的过程做一个示例,复现洗衣店的衣服洗好之后,顾客就可以来取衣服了的一个过程,代码如下:
public class Observer_01 {
//洗衣店
static class Laundry{
public void wrashClothes(){
System.out.println("衣服洗好了!");
}
public void sewClothes(){
System.out.println("衣服缝合好了!");
}
}
//客户A
static class Customer{
private String name;
public Customer(String name){
this.name = name;
}
public void take(){
System.out.println(this.name+" 取走衣服...");
}
}
public static void main(String[] args) {
Laundry laundry = new Laundry();
Customer customer = new Customer("张三");
laundry.wrashClothes();
customer.take();
System.out.println("============================");
laundry.sewClothes();
customer.take();
}
}
主要过程就一个洗衣店洗好了一件衣服,然后客户过来拿走了衣服(有可能已经来过几次,但是前几次都没有洗好),缝合好一件衣服后,另一个客户过来拿走了衣服(同样有可能也已经来过了很多次了,终于拿到了缝合好的衣服)。
从以上逻辑来看,这是一个面向过程的编程,有没有洗好或者缝合好衣服,客户根本不清楚,必须自己跑一趟,如果没有处理好,下次还得在跑一趟,太麻烦了。
下面做一下优化:
public class Observer_02 {
//洗衣店
static class Laundry{
private Customer zhangsan;
public Laundry(Customer zhangsan){
this.zhangsan = zhangsan;
}
public void wrashClothes(){
System.out.println("衣服洗好了!");
this.zhangsan.take();
}
public void sewClothes(){
System.out.println("衣服缝合好了!");
this.zhangsan.take();
}
}
//客户
static class Customer{
private String name;
public Customer(String name){
this.name = name;
}
public void take(){
System.out.println(this.name+" 取走衣服...");
}
}
public static void main(String[] args) {
Laundry laundry = new Laundry(new Customer("张三"));
laundry.wrashClothes();
System.out.println("============================");
laundry.sewClothes();
}
}
修改后的代码逻辑就好多了,洗衣店只需要保留张三客户的信息,当洗好衣服或缝好衣服后会通知张三拿走衣服,这样就不用张三来回的跑了,减少很多麻烦事儿。
但是新的问题来了,作为一个洗衣店,不可能只有一个客户存在,肯定有很多,那么每个客户的衣服洗好之后,肯定都要通知客户来拿衣服(这里先假设是洗好衣服后是按批次通知),修改后的代码如下:
public class Observer_03 {
//洗衣店
static class Laundry{
private List<Customer> customers = new ArrayList<>();
public void addCustomer(Customer customer){
this.customers.add(customer);
}
public void wrashClothes(){
System.out.println("衣服洗好了!");
this.notifyCustomers();
}
public void sewClothes(){
System.out.println("衣服缝合好了!");
this.notifyCustomers();
}
private void notifyCustomers(){
if(null!=this.customers && this.customers.size()>0){
this.customers.stream().forEach((e)->e.take());
}
}
}
//客户
static class Customer{
private String name;
public Customer(String name){
this.name = name;
}
public void take(){
System.out.println(this.name+" 取走衣服...");
}
}
public static void main(String[] args) {
Laundry laundry = new Laundry();
laundry.addCustomer(new Customer("张三"));
laundry.addCustomer(new Customer("李四"));
laundry.addCustomer(new Customer("王五"));
laundry.wrashClothes();
System.out.println("============================");
laundry.sewClothes();
}
}
这样修改后,只要当前批次的衣服处理好了,那就主动通知客户,客户就会来取走自己的衣服,这样实现就更简单了。
这就形成了一个初步的观察者模式,其中洗衣店就是被观察者(Observable),客户就是观察者(Observer),当洗衣店的某个操作处理完了,就主动告知客户,客户做出相应的动作。
实际开发中,被观察者是必须要具备以下行为的:
添加观察者
删除观察者
通知观察者做出相应的动作
而观察者必须要具备以下行为:
对通知做出相应的处理
所以根据以上的行为,我们需要抽象出一个被观察者类,将三个方法暴露给真正的被观察者实现,同时需要抽象出一个观察者,必须暴露出一个对应通知的操作,由真正的观察者来实现,所以对以上代码再次修改:
public class Observer_04 {
//被观察者
interface Obserable{
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
//观察者
interface Observer{
public void action();
}
//洗衣店
static class Laundry implements Obserable{
private List<Observer> observers = new ArrayList<>();
@Override
public void addObserver(Observer observer){
this.observers.add(observer);
}
@Override
public void removeObserver(Observer observer){
this.observers.remove(observer);
}
@Override
public void notifyObservers(){
if(null!=this.observers && this.observers.size()>0){
this.observers.stream().forEach((e)->e.action());
}
}
public void wrashClothes(){
System.out.println("衣服洗好了!");
this.notifyObservers();
}
public void sewClothes(){
System.out.println("衣服缝合好了!");
this.notifyObservers();
}
}
//客户
static class Customer implements Observer{
private String name;
public Customer(String name){
this.name = name;
}
@Override
public void action(){
System.out.println(this.name+" 取走衣服...");
}
}
public static void main(String[] args) {
Laundry laundry = new Laundry();
laundry.addObserver(new Customer("张三"));
laundry.addObserver(new Customer("李四"));
laundry.addObserver(new Customer("王五"));
laundry.wrashClothes();
System.out.println("============================");
laundry.sewClothes();
}
}
以上就是一个正常的观察者模式应用。
有时候我们作为一个观察者,可能观察的不止一个对象,有可能我还要观察我的快递有没有到达,银行转账有没有到达,这个时候就需要,根据不同的被观察者对象,进行不同的操作了,修改代码如下:
public class Observer_05 {
//被观察者
interface Obserable{
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
//观察者
interface Observer{
public void action(Obserable obserable);
}
//洗衣店
static class Laundry implements Obserable{
private List<Observer> observers = new ArrayList<>();
@Override
public void addObserver(Observer observer){
this.observers.add(observer);
}
@Override
public void removeObserver(Observer observer){
this.observers.remove(observer);
}
@Override
public void notifyObservers(){
if(null!=this.observers && this.observers.size()>0){
this.observers.stream().forEach((e)->e.action(this));
}
}
public void wrashClothes(){
System.out.println("衣服洗好了!");
this.notifyObservers();
}
public void sewClothes(){
System.out.println("衣服缝合好了!");
this.notifyObservers();
}
}
//快递
static class Expressage implements Obserable{
private List<Observer> observers = new ArrayList<>();
@Override
public void addObserver(Observer observer){
this.observers.add(observer);
}
@Override
public void removeObserver(Observer observer){
this.observers.remove(observer);
}
@Override
public void notifyObservers(){
if(null!=this.observers && this.observers.size()>0){
this.observers.stream().forEach((e)->e.action(this));
}
}
public void arrived(){
System.out.println("快递已经到达,请尽快领取...");
this.notifyObservers();
}
}
//银行
static class Bank implements Obserable{
private List<Observer> observers = new ArrayList<>();
@Override
public void addObserver(Observer observer){
this.observers.add(observer);
}
@Override
public void removeObserver(Observer observer){
this.observers.remove(observer);
}
@Override
public void notifyObservers(){
if(null!=this.observers && this.observers.size()>0){
this.observers.stream().forEach((e)->e.action(this));
}
}
public void transfer(){
System.out.println("银行转账20元已经到账...");
this.notifyObservers();
}
}
//客户
static class Customer implements Observer{
private String name;
public Customer(String name){
this.name = name;
}
@Override
public void action(Obserable obserable){
if(obserable.getClass().isAssignableFrom(Bank.class)){
System.out.println("转账终于到了,好开心...");
}else if(obserable.getClass().isAssignableFrom(Expressage.class)){
System.out.println("取快递去了...");
}else if(obserable.getClass().isAssignableFrom(Laundry.class)) {
System.out.println(this.name + " 取走衣服...");
}
}
}
public static void main(String[] args) {
Customer customer = new Customer("张三");
Laundry laundry = new Laundry();
laundry.addObserver(customer);
Bank bank = new Bank();
bank.addObserver(customer);
Expressage expressage = new Expressage();
expressage.addObserver(customer);
laundry.wrashClothes();
System.out.println("============================");
bank.transfer();
System.out.println("============================");
expressage.arrived();
}
}
以上就是观察者模式的一个演示过程,(jdk中已经提供了观察者(Observer)和被观察者(Observable)的接口)。
最后来看看观察者模式的定义:定义对象间一种一对多的依赖关系,使得每当一个对象的状态改变时,则所有依赖于它的对象都会得到通知并被自动更新。