设计模式——观察者模式
观察者模式定义一对多的依赖关系,当一个对像的状态改变时,所有依赖它的对象都将收到通知,并被自动更新。就好像你在干活儿,你的组长、主管、经理都在看着你、观察你。当你的状态变化时就通知他们所有人,他们做出相应的处理,你就是被观察的目标。要实现观察都模式,我们需要定义目标类,观察者类。
import java.util.ArrayList;
import java.util.List;
//定义一个观察目标类
public class Subject {
//定义一个列表,保存所有观察者,当状态发生改变时通知他们
private List<Observer> observers
= new ArrayList<Observer>();
//状态
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
//添加观察者的接口
public void attach(Observer observer){
observers.add(observer);
}
//状态改变时的通知接口,遍历所有观察者,并调用更新接口
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
//定义一个抽像观察者类
public abstract class Observer {
//观察目标
protected Subject subject;
//更新接口
public abstract void update();
}
//定义具体的观察者比如经理、主管、组长
public class Manager extends Observer{
public Manager(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update(){
System.out.println("我是经理,我收到了员工的通知");
}
}
//组长
public GroupLeader extends Observer{
public GroupLeader(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update(){
System.out.println("我是组长,我收到了员工的通知");
}
}
//使用示例
public class Demo{
public static void main(string[] args){
Subject subject=new Subject();
new Manager(subject);
new GroupLeader(subject);
subject.setState(10);
}
}
c++的实现
//定义一个抽像观察者类
class Observer {
//观察目标
protected:
Subject* subject;
//更新接口
public:
virtual void update() =0;
}
//定义一个观察目标类
class Subject {
//定义一个列表,保存所有观察者,当状态发生改变时通知他们
private:
std::list<Observer*> observers;
//状态
int state;
public:
int getState() {
return state;
}
void setState(int state) {
this->state = state;
notifyAllObservers();
}
//添加观察者的接口
void attach(Observer* observer){
observers.push_back(observer);
}
//状态改变时的通知接口,遍历所有观察者,并调用更新接口
void notifyAllObservers(){
for (Observer *observer : observers) {
observer->update();
}
}
}
//定义具体的观察者比如经理、主管、组长
class Manager :public Observer{
public:
Manager(Subject* subject){
this->subject = subject;
this->subject->attach(this);
}
void update() override {
std::cout << "我是经理,我收到了员工的通知" << std::endl;;
}
}
//组长
class GroupLeader :public Observer{
public: GroupLeader(Subject* subject){
this->subject = subject;
this->subject->attach(this);
}
void update() override{
std::cout << "我是组长,我收到了员工的通知" << std::endl;
}
}
//调用示例
int main(){
Subject subject;
auto a = new Manager(&subject);
auto b = new GroupLeader(&subject);
subject.setState(20);
return 0;
}
优点:
1、观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息传递机制,并抽象了更新接口,使得可以有各种各样的表示层充当具体的观察者角色。
2、观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察者对象只需要维持一个抽象观察者的集合,无需了解其具体观察者。
3、观察者模式支持广播通信,观察目标会向所有已注册的观察者发送通知,降低了一对多系统的设计难度。
4、观察者模式满足开闭原则的要求,增加新的具体观察者无须修改原有的系统代码。
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。