【Python设计模式】观察者模式

设计模式中的观察者模式是我感到比较迷惑的一种模式,刚开始接触的时候看的不太懂,因为当时在学Qt,而Qt的信号与槽的机制就有点类似于观察者模式,但是Qt却不能完全体现,以至于我在这两者之间感到有些困惑,直到后来看了《大话设计模式》后有点了解——我真的是太喜欢这本书了,后来无意中看到这篇观察者模式文章

感觉有点大彻大悟的感觉,虽然我学的是python,而博主用的是Java写的,但我认为语言其实并不是我们学习的一个难点,设计的原则与模式才是精髓,它凌驾于语言之上,是一种思想,能跨越语言之间的障碍,这里的java代码是引用了以上博主的代码,在这里我用Python复现一下吧,关于观察者模式的具体思想可以参考以上博主的文章。

文章目录

  • Java代码实现
  • Python代码实现
  • 实战演练

Java代码实现

抽象主题(Subject)角色

public class Subject {
 
     //观察者数组
     private Vector<Observer> oVector = new Vector<>();
     
     //增加一个观察者
     public void addObserver(Observer observer) {
         this.oVector.add(observer);
     }
     
     //删除一个观察者
     public void deleteObserver(Observer observer) {
         this.oVector.remove(observer);
     }
     
     //通知所有观察者
     public void notifyObserver() {
              for(Observer observer : this.oVector) {
             observer.update();
         }
     }     
 }

抽象观察者Observer

在这里要说明一下,原作者将这个解释为抽象观察者,其实是有点不太准确的,这里应该是抽象观察者更新接口,这个是每个观察者必须要实现的接口,因为被观察者更新动态后是通过调用这个接口来通知所有观察者的,为什么要用接口而不是抽象类呢?其实接口是一个动作,而类是一个属性,比如人类具有的属性就是手,但是有手不一定要打人,而打人这个动作就是一个接口,你可以打人也可以不打,所以接口可以多继承,因为你除了打这个动作还有很多动作,比如踢人,但是抽象类不同,一旦继承了抽象类就必须实现里面的所有抽象方法,比如继承人类那就要实现手和脚这两个属性或方法。

 public interface Observer {
     //更新
     public void update();
}

具体主题 (ConcreteSubject)

 public class ConcreteSubject extends Subject {
     //具体业务
     public void doSomething() {
         //...
         super.notifyObserver();
     }
 }

具体观察者(ConcreteObserver)

 public class ConcreteObserver implements Observer {
 
     @Override
     public void update() {
         System.out.println("收到消息,进行处理");
     }
 }

Client客户端

   public class Client {
     
     public static void main(String[] args) {
         //创建一个主题
          ConcreteSubject subject = new ConcreteSubject();
          //定义一个观察者
           Observer observer = new ConcreteObserver();
          //观察
         subject.addObserver(observer);
          //开始活动
        subject.doSomething();
    }
 }

Python代码实现

from abc import ABC, abstractmethod


'''抽象主题(Subject)角色'''
class Subject:
    def __init__(self):
        self.ovector = [] #观察者列表

    '''增加一个观察者'''
    def add_observer(self, observer):
        self.ovector.append(observer)

    '''删除一个观察者'''
    def delet_observer(self, observer):
        self.ovector.pop(observer)

    '''通知所有观察者'''
    def notify_observer(self):
        for observer in self.ovector:
            if object is not None:
                observer.update()


'''抽象观察者Observer'''
class Observer(ABC):
    '''更新方法'''
    @abstractmethod
    def update(self):
        pass


'''具体主题(ConcreteSubject)'''
class ConcreteSubject(Subject):
    def __init__(self):
        super().__init__()

    '''具体业务'''
    def do_something(self):
        self.notify_observer()


'''具体观察者(ConcreteObserver)'''
class ConcreteObserver(Observer):
    def update(self):
        print('收到消息,进行处理')


if __name__ == "__main__":
    subject = ConcreteSubject() #创建一个主题
    observer = ConcreteObserver() #定义一个观察者
    subject.add_observer(observer) #订阅
    subject.do_something() #开始通知

实战演练

实现一个微信朋友圈类似的功能,创建一个女生的微信和三个男生的微信,然后女生加男生的微信,最后女生发朋友圈,男生能看到女生的朋友圈,用微信朋友圈来形容观察者模式应该是很一个很好的例子了

from abc import ABC, abstractmethod

'''抽象主题(Subject)角色'''


class Subject:
    def __init__(self):
        self.ovector = []  # 观察者列表

    '''增加一个观察者'''

    def add_observer(self, observer):
        self.ovector.append(observer)

    '''删除一个观察者'''

    def delet_observer(self, observer):
        self.ovector.pop(observer)

    '''通知所有观察者'''

    def notify_observer(self, msg):
        for observer in self.ovector:
            if observer is not None:
                observer.update(msg)


'''抽象观察者Observer'''


class Observer(ABC):
    '''更新方法'''

    @abstractmethod
    def update(self, msg):
        pass


'''具体主题(ConcreteSubject)'''


class ConcreteSubject(Subject):
    def __init__(self, name):
        super().__init__()
        self.msg = None
        self.name = name

    '''具体业务'''
    def edit_msg(self, msg):
        self.msg = msg
        print(self.name + ":" + msg)

    def send_msg(self):
        self.notify_observer(self.msg)


'''具体观察者(ConcreteObserver)'''


class ConcreteObserver(Observer):
    def __init__(self, name):
        self.name = name

    def update(self, msg):
        if msg.startswith(self.name):
            print(self.name+':'+'???')
            return
        print(self.name+ ":" + '吃瓜+1')


if __name__ == "__main__":
    girl = ConcreteSubject('girl')  # 创建女生girl微信
    boy1 = ConcreteObserver('boy1') # 创建一个男生boy1微信
    boy2 = ConcreteObserver('boy2') # 创建一个男生boy2微信
    boy3 = ConcreteObserver('boy3') # 创建一个男生boy3微信
    girl.add_observer(boy1)  # 加好友
    girl.add_observer(boy2)  # 加好友
    girl.add_observer(boy3)  # 加好友
    girl.edit_msg('boy2 你这个渣男') # girl编辑一条朋友圈
    girl.send_msg()  # 发送朋友圈

运行结果有点意思,[手动吃瓜]!

girl:boy2 你这个渣男
boy1:吃瓜+1
boy2:???
boy3:吃瓜+1

这里需要注意的是python中并没有接口和虚方法的概念,所以需要用@abstractmethod方法来实现抽象接口

你可能感兴趣的:(Python设计模式)