# 观察者模式

# 概念

观察者模式(Observer Pattern)是一种软件设计模式,其核心是定义一对多的依赖关系,使多个观察者对象能同时监听某一主题对象。当主题对象状态发生变化时,所有注册的观察者对象会自动接收通知并更新自身状态。

# 作用

1.实现对象间的动态耦合,让一个对象的改变能自动通知并更新其他相关对象。

2.维护对象间的一致性和同步性,适用于需要多个对象同步更新的场景。

3.支持广播通信机制,主题对象可向所有注册的观察者发送通知。

# 场景

1.当一个对象的改变需要同时触发其他多个对象的更新时。

2.当抽象模型存在两个相互依赖的维度(如业务逻辑与展示逻辑分离)时。

3.当对象需要通知未知数量的其他对象,且具体观察者可能动态增减时。

# 举例

// 被观察者接口
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String name);
}
// 观察者接口
interface Observer {
    void update(String name);
}
// 具体的被观察者(人)
class Person implements Subject {
    private String name;
    private List<Observer> observers;

    public Person(String name) {
        this.name = name;
        this.observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String name) {
        for (Observer observer : observers) {
            observer.update(name);
        }
    }

    public void setName(String newName) {
        this.name = newName;
        notifyObservers(newName);
    }
}
// 具体的观察者(身份证)
class IDCard implements Observer {
    @Override
    public void update(String name) {
        System.out.println("身份证更新:名字已改为 " + name);
    }
}
// 具体的观察者(户口本)
class HouseholdRegister implements Observer {
    @Override
    public void update(String name) {
        System.out.println("户口本更新:名字已改为 " + name);
    }
}
// 具体的观察者(学生卡)
class StudentCard implements Observer {
    @Override
    public void update(String name) {
        System.out.println("学生卡更新:名字已改为 " + name);
    }
}

客户端测试:

// 测试类
public class Main {
    public static void main(String[] args) {
        Person person = new Person("张三");
        IDCard idCard = new IDCard();
        HouseholdRegister householdRegister = new HouseholdRegister();
        StudentCard studentCard = new StudentCard();

        person.registerObserver(idCard);
        person.registerObserver(householdRegister);
        person.registerObserver(studentCard);

        person.setName("李四");
    }
}

控制台输出:

身份证更新:名字已改为 李四
户口本更新:名字已改为 李四
学生卡更新:名字已改为 李四

# 反例

若不使用观察者模式,可通过手动维护观察者列表实现类似功能,但灵活性和通用性较低。例如:

// 被观察者(人)
class Person {
    private String name;
    private List<Runnable> updaters = new ArrayList<>();

    public Person(String name) {
        this.name = name;
    }

    public void addUpdater(Runnable updater) {
        updaters.add(updater);
    }

    public void removeUpdater(Runnable updater) {
        updaters.remove(updater);
    }

    public void setName(String newName) {
        this.name = newName;
        for (Runnable updater : updaters) {
            updater.run();
        }
    }
}
// 身份证
class IDCard {
    private Person person;

    public IDCard(Person person) {
        this.person = person;
        person.addUpdater(() -> System.out.println("身份证更新:名字已改为 " + person.name));
    }
}
// 户口本
class HouseholdRegister {
    private Person person;

    public HouseholdRegister(Person person) {
        this.person = person;
        person.addUpdater(() -> System.out.println("户口本更新:名字已改为 " + person.name));
    }
}
// 学生卡
class StudentCard {
    private Person person;

    public StudentCard(Person person) {
        this.person = person;
        person.addUpdater(() -> System.out.println("学生卡更新:名字已改为 " + person.name));
    }
}

客户端测试:

public class Main {
    public static void main(String[] args) {
        Person person = new Person("张三");
        new IDCard(person);
        new HouseholdRegister(person);
        new StudentCard(person);

        person.setName("李四");
    }
}

# 原理

观察者模式的核心原理是:主题对象维护一个观察者列表,当自身状态发生变化时,遍历该列表并调用所有观察者的更新方法。观察者通过实现统一接口(如update方法)接收通知,实现解耦。

# 缺点

观察者模式的缺点包括:

1.被观察者与观察者间的依赖关系可能变得复杂,增加维护难度。

2.观察者无法控制通知的顺序,可能导致更新逻辑依赖执行顺序的问题。

3.Java内置的ObservableObserver未考虑线程安全,需开发者自行处理并发问题。

总结

观察者模式通过一对多的依赖关系实现动态通知,适用于需要对象同步更新的场景。其优点是松耦合、支持广播通信和动态扩展,但依赖关系复杂度和通知顺序问题可能带来维护挑战。合理使用时,可有效提升系统的灵活性和可扩展性。



微信公众号

QQ交流群
原创网站开发,偏差难以避免。

如若发现错误,诚心感谢反馈。

愿你倾心相念,愿你学有所成。

愿你朝华相顾,愿你前程似锦。