Python의 디자인 패턴(2): 관찰자

소개



오늘은 옵저버 패턴을 조금 공부했습니다. 오늘 내가 한 모든 일을 이 포스트에 기록하고 싶습니다.

먼저 this website:에서 복사한 Observer 패턴에 대한 짧은 소개를 인용하고 싶습니다.

Observer pattern is used when there is one-to-many relationship between objects such as if one object is modified, its dependent objects are to be notified automatically. Observer pattern falls under behavioral pattern category.



나는 디자인 패턴에 관한 이 중국 책을 읽고 있는데 내 코딩 작업은 이 책에서 영감을 받았습니다.


이 책에 제시된 Observer 패턴의 체계는 다음과 같습니다.

대본



올해 일반적인 시나리오를 상상해 보십시오. John은 불행히도 Covid-19에 감염되었고 의료 종사자들이 진료소에서 면밀하고 주의 깊게 모니터링하고 있습니다. 그들은 체온, 심박수, 산소 포화도 등을 모니터링하기 위해 여러 의료 기기를 장착했습니다. 이 스마트 기기는 측정값이 특정 임계값을 초과하거나 미만이면 경고 신호를 전송할 수 있습니다. 오늘 저는 Python에서 Observer 패턴을 사용하여 이 시나리오를 시뮬레이션하고 싶습니다.

코딩 시작


추상 클래스



먼저 추상 클래스를 작성합니다: abstractSubjectabstractObserver .
클래스abstractSubject는 관찰 가능한 모든 대상에 대한 추상 기본 클래스입니다. 연결된 모든 관찰자를 포함하는 목록 구성원이 있습니다. 목록에 관찰자를 추가/제거하는 방법addObs()/removeObs()이 있습니다. 상태 변경을 관찰자에게 알리는 또 다른 방법notifyObservers()이 있습니다.

클래스abstractObserver는 모든 관찰자에 대한 추상 기본 클래스입니다. 여기에는 파생 클래스에 의해 재정의되고 실현되는 빈 메서드update()가 하나만 있습니다.

class abstractSubject():
    """
        Abstract Subject - Abstract patient in this demo
    """

    def __init__(self):
        self.__observers = []

    def addObs(self, observer):
        self.__observers.append(observer)

    def removeObs(self, observer):
        self.__observers.remove(observer)

    def notifyObservers(self, arg=0):
        for o in self.__observers:
            o.update(self, arg)


class abstractObserver():
    """
        Abstract Observer - Abstract medical device in this demo
    """

    def __init__(self):
        pass

    def update(self):  ## shall be overridden 
        pass


관찰할 환자



그런 다음 covidPatient 클래스에서 파생된 구체적인 클래스인 abstractSubject 클래스를 만듭니다. 이 클래스에는 공개 멤버 "이름"과 실시간 생리적 매개변수를 포함하는 비공개 dict 유형 멤버가 있습니다. 해당 메서드setValue()는 선택한 매개변수를 업데이트하고 상속된 메서드notifyObservers()를 호출하는 역할을 합니다. 방법setValue()은 선택한 생리학적 매개변수의 실시간 값을 반환합니다.

class covidPatient(abstractSubject):
    """
        Concrete Subject - Patient in this demo
    """

    def __init__(self, name):
        super().__init__()  
        self.name = name
        self.__physioParams = {"temperature": 0.0, "heartrate": 0.0, "oxygen": 0.0, "respiration": 0.0}

    ## function to the observed subject's state
    def setValue(self, measureType, val):
        if measureType in self.__physioParams:
            self.__physioParams[measureType] = val
            # print("{}'s {} set to: {}".format(self.name, measureType, str(val)) )
            self.notifyObservers()
        else:
            print("Parameter type \"{}\" not yet supported.".format(measureType))

    def getValue(self, measureType):
        if measureType in self.__physioParams:
            return self.__physioParams[measureType]
        else:
            return None


관찰자



이제 아래와 같이 두 명의 관찰자를 정의하고, 각각은 covid 환자의 특정 생리적 매개변수를 획득하고 처리하는 방법update()을 구현합니다.

class thermometer(abstractObserver):      
    """
        Concrete Observer - Thermometer
    """

    def __init__(self):
        super().__init__()


    def update(self, tt, obj):
        if tt.__class__ == covidPatient:
            temp = tt.getValue("temperature")
            if temp > 37.8:
                print("EMCY - " + "Temperature too high: " + str(temp))
            elif temp < 36.0:
                print("EMCY - " + "Temperature too slow: " + str(temp))
            else:
                print("INFO - " + "Temperature normal: " + str(temp))

        else:
            pass

class heartbeatMonitor(abstractObserver):      
    """
        Concrete Observer - heartbeat monitor
    """

    def __init__(self):
        super().__init__()

    def update(self, tt, obj):
        if tt.__class__ == covidPatient:
            hr = tt.getValue("heartrate")
            if hr > 120:
                print("EMCY - " + "Heart rate too high: " + str(hr))
            elif hr < 35:
                print("EMCY - " + "Heart rate too slow:  " + str(hr))
            else:
                print("INFO - " + "Heart rate normal: " + str(hr))

        else:
            pass


시뮬레이션 시작



자, 이제 시뮬레이션을 시작할 시간입니다. 이름이 John인 covidPatient의 인스턴스, thermometer의 인스턴스 및 heartbeatMonitor의 인스턴스를 만듭니다. 아래의 이 주요 기능은 충분히 명확하므로 더 이상 설명하지 않겠습니다.

import time

if __name__ == "__main__":
    h = covidPatient("John")
    o1 = thermometer()
    o2 = heartbeatMonitor()


    ## now kick off the simulation 
    for i in range(0, 15):

        time.sleep(1.5)
        print("====== Time step {} =======".format(i+1))

        # At rount #3: thermometer is added for monitoring temperature
        # At rount #5: heartbeatMonitor is added for monitoring heart rate
        # At rount #10: thermometer is removed

        if i == 3:
            h.addObs(o1)        
        elif i == 5:        
            h.addObs(o2)        
        elif i == 10:
            h.removeObs(o1)

        # simulating the variation of patient's physiological parameters
        if i%3 ==0:
            h.setValue("temperature", 35.5 + 0.5*i)
        elif i%3 == 1:
            h.setValue("heartrate", 30 + 10*i)
        else:
            h.setValue("oxygen", 5.0 + 0.05*i)



실행 결과:


보시다시피 환자의 생리적 매개변수는 각 시간 단계마다 다릅니다. 두 관찰자는 시뮬레이션 중에 하나씩 마운트되었으며 그 중 하나는 단계 #10에서 제거되었습니다. 두 관찰자는 비정상적인 값을 감지하자마자 비상 신호를 보냈습니다.
John이 이 성가신 코로나 바이러스에서 빨리 회복되기를...

좋은 웹페이지 즐겨찾기