当前位置: 首页 > article >正文

设计模式:观察者模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

上一篇《命令模式》                                                                    下一篇《策略模式》

简介:

观察者模式,它是一种行为型设计模式,它允许一个对象自动通知其依赖者(观察者)状态的变化。当被观察者的状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应。在观察者模式中,被观察者和观察者对象之间不需要知道对方的具体实现,只需要知道对方的接口,从而避免了紧耦合的关系。

在观察者模式中,有以下几个核心组成部分:
1、被观察者(Subject):它是一个抽象类或接口,维护一个观察者对象的列表,并定义了注册和删除观察者对象的方法。当被观察者的状态发生变化时,它负责通知所有已注册的观察者对象。
2、具体被观察者(ConcreteSubject):它是被观察者的具体实现,它维护一个状态,并定义了存储状态的方法。当它的状态发生变化时,它会通知所有已注册的观察者对象。
3、观察者(Observer):它是一个抽象类或接口,定义了更新方法以响应被观察者的状态变化。
4、具体观察者(ConcreteObserver):它是观察者的具体实现,实现了更新方法以响应被观察者的状态变化,并执行一些具体的业务逻辑处理。

在观察者模式中,被观察者和观察者之间形成了一种“一对多”的关系,当被观察者的状态发生变化时,所有注册的观察者都会得到通知并做出相应的响应。这种设计模式使得观察者与被观察者之间的耦合度降低,符合开闭原则,可以动态地增加或者删除观察者对象。然而,也需要注意避免出现循环依赖的问题,并确保在适当的时候移除观察者对象,避免内存泄漏的问题。

观察者模式的使用场景:
1、关联行为场景:观察者模式适用于建立一套触发机制的场景,例如用户关注某个商品的价格,当商品降价时进行通知,这样用户和商品产生了关联,触发机制就是商品降价。
2、事件处理系统:观察者模式可以用于实现事件处理系统,例如在购物网站中,多个用户关注某商品后,当商品降价时,就会自动通知关注该商品的用户。

总的来说,观察者模式适用于需要实现一对多的依赖关系,并且需要在对象状态改变时自动通知所有依赖者的场景。

观察者模式的创建步骤:
1、创建被观察者(Watched)类,该类通常包含一个观察者列表,以及一个用于添加、删除和通知观察者的方法。
2、创建观察者(Watcher)类,该类通常包含一个更新方法,用于在被观察者状态发生改变时更新自身状态。
3、在被观察者类中添加注册和注销观察者的方法,以便于添加和删除观察者对象。
4、在被观察者类中实现通知观察者的方法,以便于在状态发生改变时通知所有观察者对象。
5、创建具体被观察者(ConcreteWatched)类,该类继承自被观察者类,并实现具体的业务逻辑。
6、创建具体观察者(ConcreteWatcher)类,该类继承自观察者类,并实现具体的业务逻辑。
7、将具体被观察者和具体观察者对象进行组合,以便于在被观察者状态发生改变时通知所有观察者对象。

以上是观察者模式的基本创建步骤,需要注意的是,在实际应用中可能需要根据具体情况进行调整和优化。

观察者模式的优点,主要包括:
1、实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
2、在观察目标和观察者之间建立一个抽象的耦合,观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
3、支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
4、符合“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。

观察者模式的缺点,主要包括:
1、如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

因此,在使用观察者模式时需要注意以上问题,避免出现不必要的缺陷。


示例:


一、C#观察者模式

以下是一个示例,展示了如何在C#中实现观察者模式:

//首先,定义一个被观察者接口:
public interface ISubject  
{  
    void Register(IObserver observer);  
    void Remove(IObserver observer);  
    void Notify();  
}
//然后,定义一个具体被观察者类:
public class ConcreteSubject : ISubject  
{  
    private List<IObserver> observers;  
    private string state;  
  
    public ConcreteSubject()  
    {  
        observers = new List<IObserver>();  
    }  
  
    public void Register(IObserver observer)  
    {  
        observers.Add(observer);  
    }  
  
    public void Remove(IObserver observer)  
    {  
        observers.Remove(observer);  
    }  
  
    public void Notify()  
    {  
        foreach (var observer in observers)  
        {  
            observer.Update(state);  
        }  
    }  
  
    public void SetState(string state)  
    {  
        this.state = state;  
        Notify();  
    }  
}
//接下来,定义一个观察者接口:
public interface IObserver  
{  
    void Update(string state);  
}
//最后,定义一个具体观察者类:
public class ConcreteObserver : IObserver  
{  
    private string name;  
    public ConcreteObserver(string name)  
    {  
        this.name = name;  
    }  
    public void Update(string state)   
    {   
        Console.WriteLine("{0} received update and the new state is {1}", name, state);   
    }   
}   
//接下来,可以创建一个具体的被观察者和多个具体观察者,并实现它们之间的交互:
public static void Main(string[] args){
    ISubject subject = new ConcreteSubject(); 
    
    IObserver observer1 = new ConcreteObserver("Observer 1");
    IObserver observer2 = new ConcreteObserver("Observer 2"); 
    IObserver observer3 = new ConcreteObserver("Observer 3"); 
    
    subject.Register(observer1); 
    subject.Register(observer2); 
    subject.Register(observer3); 
    subject.SetState("New State"); 
} 

在这个示例中,我们创建了一个被观察者对象subject和一个观察者对象observer1、observer2和observer3。我们将这些观察者对象注册到被观察者对象subject中,然后调用subject的SetState方法来改变其状态。当状态发生变化时,所有注册的观察者都会自动收到通知并执行Update方法。
在这个例子中,我们只是简单地打印出每个观察者的名称和新的状态。你可以根据自己的需求扩展这个示例。

二、java观察者模式

观察者模式通常通过以下方式实现:

public interface Subject {  
    void register(Observer observer);  
    void remove(Observer observer);  
    void notifyObservers(String message);  
}
public class ConcreteSubject implements Subject {  
    private List<Observer> observers;  
    private String message;  
  
    public ConcreteSubject() {  
        observers = new ArrayList<>();  
    }  
  
    @Override  
    public void register(Observer observer) {  
        observers.add(observer);  
    }  
  
    @Override  
    public void remove(Observer observer) {  
        observers.remove(observer);  
    }  
  
    @Override  
    public void notifyObservers(String message) {  
        for (Observer observer : observers) {  
            observer.update(message);  
        }  
    }  
  
    public void setMessage(String message) {  
        this.message = message;  
        notifyObservers(message);  
    }  
} 

public interface Observer {  
    void update(String message);  
}
class ConcreteObserver implements Observer {  
    private String name;  
  
    public ConcreteObserver(String name) {  
        this.name = name;  
    }  
  
    @Override  
    public void update(String message) {  
        System.out.println(name + " received update with message: " + message);  
    }  
}  
public class Main {  
    public static void main(String[] args) {  
        Subject subject = new ConcreteSubject();  
        Observer observer1 = new ConcreteObserver("Observer 1");  
        Observer observer2 = new ConcreteObserver("Observer 2");  
        Observer observer3 = new ConcreteObserver("Observer 3");  
        subject.register(observer1);  
        subject.register(observer2);  
        subject.register(observer3);  
        subject.setMessage("Hello World!");  
    }  
}

三、javascript观察者模式

在JavaScript中实现观察者模式,通常需要定义一个被观察者(Subject)和一个或多个观察者(Observer)。被观察者维护一个观察者列表,并在状态发生变化时遍历这个列表并调用每个观察者的更新方法。

下面是一个简单的JavaScript观察者模式的代码示例:

class Subject {  
  constructor() {  
    this.observers = [];  
  }  
  
  subscribe(observer) {  
    this.observers.push(observer);  
  }  
  
  unsubscribe(observer) {  
    this.observers = this.observers.filter(obs => obs !== observer);  
  }  
  
  notify(message) {  
    this.observers.forEach(observer => observer.update(message));  
  }  
}  
  
class Observer {  
  constructor(name) {  
    this.name = name;  
  }  
  
  update(message) {  
    console.log(`${this.name} received update with message: ${message}`);  
  }  
}  
  
// 使用示例  
const subject = new Subject();  
const observer1 = new Observer("Observer 1");  
const observer2 = new Observer("Observer 2");  
const observer3 = new Observer("Observer 3");  
subject.subscribe(observer1);  
subject.subscribe(observer2);  
subject.subscribe(observer3);  
subject.notify("Hello World!");

四、C++观察者模式

以下是在C++中实现观察者模式:

//定义一个观察者接口
class Observer {  
public:  
    virtual void update(Subject* subject) = 0;  
};
//定义一个被观察者接口
class Subject {  
public:  
    virtual void registerObserver(Observer* observer) = 0;  
    virtual void removeObserver(Observer* observer) = 0;  
    virtual void notifyObservers() = 0;  
};
//创建一个具体被观察者类
class ConcreteSubject : public Subject {  
private:  
    std::vector<Observer*> observers;  
  
public:  
    void registerObserver(Observer* observer) override {  
        observers.push_back(observer);  
    }  
  
    void removeObserver(Observer* observer) override {  
        for (auto it = observers.begin(); it != observers.end(); ++it) {  
            if (*it == observer) {  
                observers.erase(it);  
                break;  
            }  
        }  
    }  
  
    void notifyObservers() override {  
        for (auto observer : observers) {  
            observer->update(this);  
        }  
    }  
};
//创建一个具体观察者类
class ConcreteObserver : public Observer {  
private:  
    std::string name;  
  
public:  
    ConcreteObserver(std::string name) : name(name) {}  
  
    void update(Subject* subject) override {  
        std::cout << name << " received update." << std::endl;  
    }  
};
//使用示例:
int main() {  
    ConcreteSubject subject;  
    ConcreteObserver observer1("Observer 1");  
    ConcreteObserver observer2("Observer 2");  
    ConcreteObserver observer3("Observer 3");  
    subject.registerObserver(&observer1);  
    subject.registerObserver(&observer2);  
    subject.registerObserver(&observer3);  
    subject.notifyObservers(); // 输出:Observer 1 received update. Observer 2 received update. Observer 3 received update.  
    subject.removeObserver(&observer2); // 删除一个观察者  
    subject.notifyObservers(); // 输出:Observer 1 received update. Observer 3 received update.  
    return 0;  
}

五、python观察者模式

在Python中实现观察者模式,通常需要定义一个被观察者类和一个或多个观察者类。被观察者类维护一个观察者列表,并在状态发生变化时遍历这个列表并调用每个观察者的更新方法。
以下是在python中实现观察者模式:

class Subject:  
    def __init__(self):  
        self._observers = []  
          
    def attach(self, observer):  
        self._observers.append(observer)  
          
    def detach(self, observer):  
        self._observers.remove(observer)  
          
    def notify(self, value=None):  
        for observer in self._observers:  
            observer.update(value)  
              
class Observer:  
    def update(self, value):  
        pass  
          
class ConcreteObserver(Observer):  
    def update(self, value):  
        print(f"Observer received update with value: {value}")  
          
# 使用示例  
subject = Subject()  
observer1 = ConcreteObserver()  
observer2 = ConcreteObserver()  
observer3 = ConcreteObserver()  
subject.attach(observer1)  
subject.attach(observer2)  
subject.attach(observer3)  
subject.notify(100) # 输出:Observer received update with value: 100 Observer received update with value: 100 Observer received update with value: 100   
subject.detach(observer2) # 删除一个观察者  
subject.notify(200) # 输出:Observer received update with value: 200 Observer received update with value: 200

六、go观察者模式

以下是一个示例,展示了如何在go中实现观察者模式:

type Subject struct {  
    observers []Observer  
}  
  
func (s *Subject) Attach(observer Observer) {  
    s.observers = append(s.observers, observer)  
}  
  
func (s *Subject) Notify() {  
    for _, observer := range s.observers {  
        observer.Update()  
    }  
}  
  
typeObserver interface {  
    Update()  
}  
  
typeConcreteObserver struct {  
    name string  
}  
  
func (o *ConcreteObserver) Update() {  
    fmt.Printf("Observer %s received update.\n", o.name)  
}

在这个示例中,我们定义了一个被观察者结构体Subject,它维护一个观察者列表observers。我们定义了一个Attach方法用于将一个观察者添加到观察者列表中,以及一个Notify方法用于遍历观察者列表并调用每个观察者的Update方法。我们定义了一个观察者接口Observer,它包含一个Update方法。最后,我们创建了一个具体观察者结构体ConcreteObserver,它实现了Observer接口的Update方法。在主函数中,我们创建了一个被观察者对象subject和一个具体观察者对象observer,并将它们分别添加到被观察者和观察者列表中。然后我们调用被观察者的Notify方法来通知所有注册的观察者状态变化。

七、PHP观察者模式

以下是一个示例,展示了如何在PHP中实现观察者模式:

//定义一个主题接口(Subject):
interface Subject {  
    public function attach(Observer $observer);  
    public function detach(Observer $observer);  
    public function notify(Observer $observer);  
}
//定义一个具体主题类(ConcreteSubject):
class ConcreteSubject implements Subject {  
    private $observers = [];  
    private $state;  
  
    public function attach(Observer $observer) {  
        $this->observers[] = $observer;  
    }  
  
    public function detach(Observer $observer) {  
        $index = array_search($observer, $this->observers);  
        if ($index !== false) {  
            unset($this->observers[$index]);  
        }  
    }  
  
    public function notify(Observer $observer) {  
        foreach ($this->observers as $observer) {  
            $observer->update($this->state);  
        }  
    }  
  
    public function setState($state) {  
        $this->state = $state;  
        $this->notify($this->observers);  
    }  
}
//定义一个观察者接口(Observer):
interface Observer {  
    public function update($state);  
}
//定义一个具体观察者类(ConcreteObserver):
class ConcreteObserver implements Observer {  
    private $name;  
  
    public function __construct($name) {  
        $this->name = $name;  
    }  
  
    public function update($state) {  
        echo "Observer {$this->name} received update with state: {$state}\n";  
    }  
}

// 创建具体观察者对象  
$observer1 = new ConcreteObserver("Observer 1");  
$observer2 = new ConcreteObserver("Observer 2");  
$observer3 = new ConcreteObserver("Observer 3");  
  
// 创建具体主题对象并附加观察者对象  
$subject = new ConcreteSubject();  
$subject->attach($observer1);  
$subject->attach($observer2);  
$subject->attach($observer3);  
  
// 设置主题状态并通知观察者对象更新状态信息  
$subject->setState("new state");

  
《完结》

上一篇《命令模式》                                                                    下一篇《策略模式》


http://www.kler.cn/a/105351.html

相关文章:

  • 不开源项目aspose.cells最新版23.10的一些科普
  • 性能测试的指南:测试类型、性能测试步骤、最佳实践等!
  • rapidocr_paddle[gpu]:GPU端推理库来了
  • Flutter GetX使用详解
  • muduo源码剖析之AsyncLogging异步日志类
  • Kafka - 图解生产者消息发送流程
  • UE5 Blueprint发送http请求
  • MarkDown详细入门笔记
  • 软考系列(系统架构师)- 2014年系统架构师软考案例分析考点
  • server error: Preprocessor dependency “less“ not found. Did you install it?
  • Java Boolean类,Java Character类,Java Number类
  • 【Java-框架-SpringMVC】(01) SpringMVC框架的简单创建与使用,快速上手 - 简易版
  • Tomcat+nginx负载均衡和动静分离
  • 【Tailwind CSS】当页面内容过少,怎样让footer保持在屏幕底部?
  • 2023 10月最新Vmd 下载安装教程,WindowsLinux
  • 【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建
  • yyds,Elasticsearch Template自动化管理新索引创建
  • mysql创建自定义函数报错
  • 论文-分布式-分布式计算|容错-分布式控制下的自稳定系统
  • C#实现数据导出任一Word图表的通用呈现方法及一些体会