成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python之單例模式和工廠模式

jayce / 2489人閱讀

摘要:在工廠方法模式中,我們會遇到一個問題,當產(chǎn)品非常多時,繼續(xù)使用工廠方法模式會產(chǎn)生非常多的工廠類。從簡單工廠模式到抽象工廠模式,我們都是在用后一種模式解決前一種模式的缺陷,都是在最大程度降低代碼的耦合性。

單例模式

所謂單例模式,也就是說不管什么時候我們要確保只有一個對象實例存在。很多情況下,整個系統(tǒng)中只需要存在一個對象,所有的信息都從這個對象獲取,比如系統(tǒng)的配置對象,或者是線程池。這些場景下,就非常適合使用單例模式。總結(jié)起來,就是說不管我們初始化一個對象多少次,真正干活的對象只會生成一次并且在首次生成。

我們可以使用單例模式來保證連接數(shù)據(jù)庫只會發(fā)生一次。下面我們看看一個簡單的 Flask Web 框架的 sqlite 擴展。

-- coding: utf-8 --

import sqlite3
from flask import current_app
from flask import _app_ctx_stack as stack

class SQLite3(object):

def __init__(self, app=None):
    self.app = app
    if app is not None:
        self.init_app(app)

def init_app(self, app):
    """ 
    典型的 Flask 擴展的初始化方式
    """
    app.config.setdefault("SQLITE3_DATABASE", ":memory:")
    app.teardown_appcontext(self.teardown)

def connect(self):
    """ 
    連接到 sqlite 數(shù)據(jù)庫
    """
    return sqlite3.connect(current_app.config["SQLITE3_DATABASE"])

def teardown(self, exception):
      """ 
      關(guān)閉 sqlite 鏈接
      """
    ctx = stack.top
    if hasattr(ctx, "sqlite3_db"):
        ctx.sqlite3_db.close()

@property
def connection(self):
    """ 
    單例模式在這里:使用 flask._app_ctx_stack 存放 sqlite 鏈接, 
    每次獲取數(shù)據(jù)庫鏈接時都通過 connection 獲取
    """
    ctx = stack.top
    if ctx is not None:
        if not hasattr(ctx, "sqlite3_db"):
            ctx.sqlite3_db = self.connect()
        return ctx.sqlite3_db

在以上的代碼中,我們每次使用數(shù)據(jù)庫的時候通過 SQLite3.connection 獲取數(shù)據(jù)庫連接就可以了。SQLite3.connection保證了數(shù)據(jù)庫連接只會發(fā)生一次,其原理和之前我們實現(xiàn)單例模式的方式相同,只不過這里存儲實例的地方變成 flask._app_ctx_stack了。

可以看到單例模式的實現(xiàn)只需要找一個變量存放創(chuàng)建的實例,然后每次獲取實例時,先檢查變量中是否已保存實例,如果沒有則創(chuàng)建一個實例并將其存放到變量中,以后都從這個變量中獲取實例就可以了。單例模式中,只會創(chuàng)建一次實例。

工廠模式

“工廠”兩字,一目了然。所謂工廠模式,也就是說我們可以通過工廠類創(chuàng)建產(chǎn)品。

在工廠方法模式中,我們會遇到一個問題,當產(chǎn)品非常多時,繼續(xù)使用工廠方法模式會產(chǎn)生非常多的工廠類。

現(xiàn)在我們有一個產(chǎn)品是課程,但是僅僅依靠課程還沒辦法提供完美的服務(wù),因為在 實驗樓 你可以邊學課程邊做實驗?zāi)?。在哪里做實驗?zāi)兀慨斎皇窃谔摂M機里了。當然我們也有很多種虛擬機,比如 Linux 虛擬機和 Mac 虛擬機。

如果按照工廠方法模式的作法,我們需要創(chuàng)建 Linux 虛擬機工廠類和 Mac 虛擬機工廠類, 這樣我們就會有一堆工廠類了。但是在 實驗樓 里,真正的情況是只有虛擬機和課程結(jié)合在一起才能給用戶提供完美的服務(wù)。我們就不能創(chuàng)建出一個能同時創(chuàng)建課程和虛擬機的工廠嗎?因為我們知道其實用戶的需求同時包含了課程和虛擬機,如果有一座工廠能同時生產(chǎn)這兩種產(chǎn)品就完美了。

-- coding: utf-8 --

import random
import abc

兩種類型的課程

class BasicCourse(object):

"""
基礎(chǔ)課程
"""
def get_labs(self):
    return "basic_course: labs"

def __str__(self):
    return "BasicCourse"

class ProjectCourse(object):

"""
項目課
"""

def get_labs(self):
    return "project_course: labs"

def __str__(self):
    return "ProjectCourse"

兩種類型的虛擬機

class LinuxVm(object):

"""
Linux 虛擬機
"""

def start(self):
    return "Linux vm running"

class MacVm(object):

"""
Mac OSX 虛擬機
"""

def start(self):
    return "Mac OSX vm running"

class Factory(metaclass=abc.ABCMeta):

"""
抽象工廠類, 現(xiàn)在工廠類不僅能創(chuàng)建課程,還能創(chuàng)建虛擬機了
"""

@abc.abstractmethod
def create_course(self):
    pass

@abc.abstractmethod
def create_vm(self):
    pass

class BasicCourseLinuxFactory(Factory):

"""
基礎(chǔ)課程工廠類
"""

def create_course(self):
    return BasicCourse()

def create_vm(self):
    return LinuxVm()

class ProjectCourseMacFactory(Factory):

"""
項目課程工廠類
"""

def create_course(self):
    return ProjectCourse()

def create_vm(self):
    return MacVm()

def get_factory():

"""
隨機獲取一個工廠類
"""
return random.choice([BasicCourseLinuxFactory, ProjectCourseMacFactory])()

if name == "__main__":

factory = get_factory()
course = factory.create_course()
vm = factory.create_vm()
print(course.get_labs())
print(vm.start())

抽象工廠模式順利的解決了工廠方法模式中遇到的問題,我們通過將產(chǎn)品的創(chuàng)建進行組合放入一個工廠類中,不但減少了工廠類的數(shù)量,還增加了生產(chǎn)產(chǎn)品體系的能力(比如課程和虛擬機組成了一個產(chǎn)品體系)實驗樓?,F(xiàn)在,工廠類不僅僅能創(chuàng)建課程,還能創(chuàng)建虛擬機,我們只需要一座工廠就能為 實驗樓 用戶服務(wù)啦 。

從簡單工廠模式到抽象工廠模式,我們都是在用后一種模式解決前一種模式的缺陷,都是在最大程度降低代碼的耦合性。在使用工廠模式家族時,不管使用哪一種工廠模式,只要能達到最大程度的解耦,都是不錯的選擇。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/44121.html

相關(guān)文章

  • 優(yōu)才公開課筆記:php設(shè)計模式(一) 單例模式

    摘要:最近開展了三次設(shè)計模式的公開課,現(xiàn)在來總結(jié)一下設(shè)計模式在中的應(yīng)用,這是第一篇創(chuàng)建型模式之單例模式。不過因為不支持多線程所以不需要考慮這個問題了。 最近開展了三次設(shè)計模式的公開課,現(xiàn)在來總結(jié)一下設(shè)計模式在PHP中的應(yīng)用,這是第一篇創(chuàng)建型模式之單例模式。 一、設(shè)計模式簡介 首先我們來認識一下什么是設(shè)計模式: 設(shè)計模式是一套被反復(fù)使用、容易被他人理解的、可靠的代碼設(shè)計經(jīng)驗的總結(jié)。 設(shè)計模式不...

    guyan0319 評論0 收藏0
  • Java基礎(chǔ)學習——多線程單例設(shè)計模式(轉(zhuǎn))

    摘要:總之,選擇單例模式就是為了避免不一致狀態(tài),避免政出多頭。二餓漢式單例餓漢式單例類在類初始化時,已經(jīng)自行實例化靜態(tài)工廠方法餓漢式在類創(chuàng)建的同時就已經(jīng)創(chuàng)建好一個靜態(tài)的對象供系統(tǒng)使用,以后不再改變,所以天生是線程安全的。 概念:  Java中單例模式是一種常見的設(shè)計模式,單例模式的寫法有好幾種,這里主要介紹兩種:懶漢式單例、餓漢式單例?! 卫J接幸韵绿攸c:  1、單例類只能有一個實例?!?..

    dendoink 評論0 收藏0
  • 每天一個設(shè)計模式單例模式

    摘要:博主按每天一個設(shè)計模式旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實現(xiàn)。單例模式用途如果一個類負責連接數(shù)據(jù)庫的線程池日志記錄邏輯等等,此時需要單例模式來保證對象不被重復(fù)創(chuàng)建,以達到降低開銷的目的。 博主按:《每天一個設(shè)計模式》旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)兩種語言實現(xiàn)。誠然,每種設(shè)計模式都有多種實...

    yy736044583 評論0 收藏0
  • 每天一個設(shè)計模式單例模式

    摘要:博主按每天一個設(shè)計模式旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實現(xiàn)。單例模式用途如果一個類負責連接數(shù)據(jù)庫的線程池日志記錄邏輯等等,此時需要單例模式來保證對象不被重復(fù)創(chuàng)建,以達到降低開銷的目的。 博主按:《每天一個設(shè)計模式》旨在初步領(lǐng)會設(shè)計模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)兩種語言實現(xiàn)。誠然,每種設(shè)計模式都有多種實...

    lijy91 評論0 收藏0
  • python單例模式實現(xiàn)的三種方式

    摘要:輸出結(jié)果輸出結(jié)果此外還有兩種實現(xiàn)單例的方式,我呢也給大家列出來,方便大家學習和參考方式一方式二單例模式實現(xiàn)方式二。。。 什么是單例模式?通俗點講:單例模式就是在程序執(zhí)行的過程中,類只有一個實例,這不是說單例模式只能去創(chuàng)建一個實例,而是你創(chuàng)建的所有實例(也就是對象)都指的是同一個實例。如何做到這一點呢?我們的__new__特殊方法就派上用場了,可能大家對這個方法熟悉又陌生,那么接下來通過...

    dack 評論0 收藏0

發(fā)表評論

0條評論

jayce

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<