Рубрики
Без рубрики

Шаблон дизайна в Python (1): Singleton

Задний план Это было несколько лет назад, что я узнал и использовал узоры дизайна во время моих … Помечено с Python, дизайн, синглтон, шаблон.

Задний план

Это было несколько лет назад, что я узнал и использовал Дизайн шаблонов во время моей предыдущей работы. Мы разработали программное обеспечение для медицинских роботов в C ++ (I.e OOP) и разные образцы дизайна часто использовались в нашем коде. Позже, когда я начал работать в нашем стартапе, мы много развиваем в Python и HTML5 Для больших данных и веб-проектов, таким образом, мы используем вряд ли узоров дизайна.

Недавно я читаю эту книгу о Дизайн шаблонов как показано ниже:

Эта книга очень интересная, и это заставляет меня вспоминать знания о проектных узорах. Я понимаю, что мне пора проводить упражнения на рисунке дизайна в Питон .

Singleton упражнения

Итак, сегодня я попробовал простой сценарий для реализации Singleton в Python Отказ Я хочу имитировать случай, когда пользователь называет Siri играть музыку.

ИДТИ!

Нет Синглтон Сейс

Определите обычный класс игрока без внедрения Singleton.

import threading
import time

## a global album dict containing three music as well as their length 
album = {"Love Story":10, "Angels":12, "Elle":18}

### a regular MusicPlayer class which contains a thread for simulating music playing
### 普通的播放器类,自带一个播放线程
class musicplayer():      
    """
        a regular MusicPlayer class 
    """

    def __init__(self):
        self.__currentItem = ""
        self.__musicLength = 0
        self.__timer = 0
        self.__thread = threading.Thread(target=self.playsound)


    def play(self):
        if  self.__thread.isAlive():
            pass
        else:
            self.__thread.start()

    def updateItem(self, musicfile, length):
        self.__currentItem = musicfile
        self.__musicLength = length
        self.__timer = 0

    def playsound(self):

        while self.__timer <= self.__musicLength:
            print(" -- playing   {}  ---- {}.00/{}.00" .format(self.__currentItem, self.__timer, self.__musicLength))
            time.sleep(1)
            self.__timer +=1
        print("{} playing thread has ended".format(self.__currentItem))

Теперь определите довольно простой класс Siri, который имеет только одну функцию runcmd Для инициализации приложения игрока и воспроизведения музыки.

class Siri():

    def __init__(self):
        pass

    def runCMD(self, cmd):
        if cmd.startswith("play music"):
            music = cmd.replace("play music", "").strip()
            player = musicplayer()
            player.updateItem(music, album[music])
            player.play()

Теперь попробуйте в Главная функция.

if __name__ == "__main__":
    musicList = list(album.keys())
    siri = Siri()
    siri.runCMD("play music {}".format(musicList[0]))
    time.sleep(4)
    siri.runCMD("play music {}".format(musicList[1]))

    mainTime = 0

    while (mainTime < 20):
        mainTime+=1
        time.sleep(1)

    print("End of simulation")

Выполните код выше, я вижу, что были созданы два музыкальных игрока, и они одновременно играли разные предметы.

Singleton Case.

Теперь я немного обновляю класс музыкального проигрывателя, так что это класс Singleton-Pattern. Этот класс получен из объект Класс, так что мне нужно определить __new __ () и __init __ () функции для работы конструктора.

class musicplayer(object):      
    """
        ### a SINGLETON MusicPlayer class which contains a thread for simulating music playing
    """
    __instance = None
    __isInstanceDefined = False

    def __new__(cls):
        if not cls.__instance:
            musicplayer.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self):
        if not musicplayer.__isInstanceDefined:  
            self.__currentItem = ""
            self.__musicLength = 0
            self.__timer = 0
            self.__thread = threading.Thread(target=self.playsound)
            musicplayer.__isInstanceDefined = True
        else:
            pass


    def play(self):
        if  self.__thread.isAlive():
            pass
        else:
            self.__thread.start()

    def updateItem(self, musicfile, length):
        self.__currentItem = musicfile
        self.__musicLength = length
        self.__timer = 0

    def playsound(self):

        while self.__timer <= self.__musicLength:
            print(" -- playing   {}  ---- {}.00/{}.00" .format(self.__currentItem, self.__timer, self.__musicLength))
            time.sleep(1)
            self.__timer +=1
        print("{} playing thread has ended".format(self.__currentItem))

Теперь снова выполните весь файл кода, и он работает. Существует один и только один экземпляр игрока в моделировании даже Siri изменил музыкальный элемент:

Синглтон декоратор

В книге я прочитал, автор ввел очень изящный способ понять Singleton Узор без модификации существующих классов: используя декоратор. Мне очень нравится этот метод.

Этот метод декоратора явный и простой:

def singletonDecorator(cls, *args, **kwargs):
    """ defines a Singleton decorator """
    instance = {}

    def wrapperSingleton(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]

    return wrapperSingleton

Теперь я поставил весь файл кода здесь. Обратите внимание, что есть @singletonecorator Декларация выше моего существующего MusicPlayer класс:

import threading
import time

album = {"Love Story":10, "Angels":12, "Elle":18}


def singletonDecorator(cls, *args, **kwargs):
    """ defines a Singleton decorator """
    instance = {}

    def wrapperSingleton(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]

    return wrapperSingleton

### a regular MusicPlayer class which contains a thread for simulating music playing
### 普通的播放器类,自带一个播放线程
@singletonDecorator
class musicplayer():         
    """
        a regular MusicPlayer class 
    """

    def __init__(self):
        self.__currentItem = ""
        self.__musicLength = 0
        self.__timer = 0
        self.__thread = threading.Thread(target=self.playsound)


    def play(self):
        if  self.__thread.isAlive():
            pass
        else:
            self.__thread.start()

    def updateItem(self, musicfile, length):
        self.__currentItem = musicfile
        self.__musicLength = length
        self.__timer = 0

    def playsound(self):

        while self.__timer <= self.__musicLength:
            print(" -- playing   {}  ---- {}.00/{}.00" .format(self.__currentItem, self.__timer, self.__musicLength))
            time.sleep(1)
            self.__timer +=1
        print("{} playing thread has ended".format(self.__currentItem))

class Siri():

    def __init__(self):
        pass

    def runCMD(self, cmd):
        if cmd.startswith("play music"):
            music = cmd.replace("play music", "").strip()
            player = musicplayer() 
            player.updateItem(music, album[music])
            player.play()



if __name__ == "__main__":


    musicList = list(album.keys())
    siri = Siri()
    siri.runCMD("play music {}".format(musicList[0]))
    time.sleep(4)
    siri.runCMD("play music {}".format(musicList[1]))

    mainTime = 0


    while (mainTime < 20):
        mainTime+=1
        time.sleep(1)

    print("End of simulation")

Этот новый метод дает тот же результат:

Оригинал: “https://dev.to/jemaloqiu/design-pattern-in-python-singleton-5apj”