资讯专栏INFORMATION COLUMN

比较全面的单例模式和工厂模式

chemzqm / 851人阅读

摘要:还有一个工厂类。工厂类有一个方法名有两个输入参数,名字和性别。用户使用工厂类,通过调用方法。抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

概念
工厂模式:工厂模式就是不管如何实现的,只需要调用抽象话的接口就可以创建出特定类型的实例对象

简单工厂模式:
eg:一个例子更能很好的理解以上的内容:
我们有一个基类Person ,包涵获取名字,性别的方法 。有两个子类male 和female,可以打招呼。还有一个工厂类。
工厂类有一个方法名getPerson有两个输入参数,名字和性别。
用户使用工厂类,通过调用getPerson方法。

在程序运行期间,用户传递性别给工厂,工厂创建一个与性别有关的对象。因此工厂类在运行期,决定了哪个对象应该被创建。

class Person:

def __init__(self):
    self.name = None
    self.gender = None

def getName(self):
    return self.name

def getGender(self):
    return self.gender

class Male(Person):

def __init__(self, name):
    print "Hello Mr." + name

class Female(Person):

def __init__(self, name):
    print "Hello Miss." + name

class Factory:

def getPerson(self, name, gender):
    if gender == ‘M":
            return Male(name)
        if gender == "F":
        return Female(name)

if name == "__main__":

factory = Factory()
person = factory.getPerson("Chetan", "M")


抽象工厂模式:
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
class Burger():

"""
汉堡
"""
name=""
price=0.0
type="BURGER"
def getPrice(self):
    return self.price
def setPrice(self,price):
    self.price=price
def getName(self):
    return self.name

class CheeseBurger(Burger):

def __init__(self):
    self.name="cheese burger"
    self.price=10.0

class SpicyChickenBurger(Burger):

def __init__(self):
    self.name="spicy chicken burger"
    self.price=15.0

class Snack():

"""
小食类
"""
name = ""
price = 0.0
type = "SNACK"
def getPrice(self):
    return self.price
def setPrice(self, price):
    self.price = price
def getName(self):
    return self.name

class Chips(Snack):

def __init__(self):
    self.name = "chips"
    self.price = 6.0

class ChickenWings(Snack):

def __init__(self):
    self.name = "chicken wings"
    self.price = 12.0

class Beverage():

"""
饮料
"""
name = ""
price = 0.0
type = "BEVERAGE"
def getPrice(self):
    return self.price
def setPrice(self, price):
    self.price = price
def getName(self):
    return self.name

class Coke(Beverage):

def __init__(self):
    self.name = "coke"
    self.price = 4.0

class Milk(Beverage):

def __init__(self):
    self.name = "milk"
    self.price = 5.0
以上的Burger,Snack,Beverage,都可以认为是该快餐店的产品,由于只提供了抽象方法,我们把它们叫抽象产品类,而cheese burger等6个由抽象产品类衍生出的子类,叫作具体产品类。

class FoodFactory():

"""
抽象工厂foodFactory为抽象的工厂类,而burgerFactory,snackFactory,beverageFactory为具体的工厂类。
"""
type=""
def createFood(self,foodClass):
    print(self.type," factory produce a instance.")
    foodIns=foodClass()
    return foodIns

class BurgerFactory(foodFactory):

def __init__(self):
    self.type="BURGER"

class SnackFactory(foodFactory):

def __init__(self):
    self.type="SNACK"

class BeverageFactory(foodFactory):

def __init__(self):
    self.type="BEVERAGE"

if __name__=="__main__":

burger_factory=burgerFactory()
snack_factory=snackFactory()
beverage_factory=beverageFactory()
cheese_burger=burger_factory.createFood(cheeseBurger)
print(cheese_burger.getName(),cheese_burger.getPrice())
chicken_wings=snack_factory.createFood(chickenWings)
print(chicken_wings.getName(),chicken_wings.getPrice())
coke_drink=beverage_factory.createFood(coke)
print(coke_drink.getName(),coke_drink.getPrice())

工厂模式优点
工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节 能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部 在系统中加入新产品时,完全符合开闭原则
工厂模式缺点
系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销 增加了系统的抽象性和理解难度
工厂模式适用环境
客户端不知道它所需要的对象的类(客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体产品对象由具体工厂类创建) 抽象工厂类通过其子类来指定创建哪个对象

抽象工厂模式:
模式优点
隔离了具体类的生成,使得客户端并不需要知道什么被创建 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象 增加新的产品族很方便,无须修改已有系统,符合开闭原则
模式缺点
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则
模式适用环境
一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节 系统中有多于一个的产品族,但每次只使用其中某一产品族 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构

单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。 eg:系统中的打印机
实现方式:
使用模块:
在mysingleton.py模块文件中:(因为模块在第一次导入时生成了.pyc文件,下次会直接从这个里面加载,不需要重新生成)
class Singleton:(object):

 def foo(self):
   pass

singleton = Singeton()

在其他文件中调用:
from mysingleton import singleton
使用装饰器:
def Singleton(cls):

_instance = {}

def _singleton(*args, **kargs):
此处是核心代码
    if cls not in _instance:
        _instance[cls] = cls(*args, **kargs)
    return _instance[cls]
此处是核心代码
return _singleton

@Singleton
class A(object):

a = 1

def __init__(self, x=0):
    self.x = x

a1 = A(2)
a2 = A(3)
print(id(a1))
print(id(a2))

使用类
import time
import threading
class Singleton(object):

_instance_lock = threading.Lock()

def __init__(self):
    time.sleep(1)

@classmethod
def instance(cls, *args, **kwargs):
    if not hasattr(Singleton, "_instance"):
        with Singleton._instance_lock:
            if not hasattr(Singleton, "_instance"):
                Singleton._instance = Singleton(*args, **kwargs)
    return Singleton._instance

def task(arg):

obj = Singleton.instance()
print(obj)

for i in range(10):

t = threading.Thread(target=task,args=[i,])
t.start()

time.sleep(20)
obj = Singleton.instance()
print(obj)

考虑了多线程问题,进行加锁,避免运行太快,如果在__init__中有IO操作,造成创建单例失败,,最后优化必须通过obj= Singleton.instance()来实现单例,如果是obj = Singleton()创建的不是单例

基于__new__方法创建单例
import threading
class Singleton(object):

_instance_lock = threading.Lock()

def __init__(self):
    pass


def __new__(cls, *args, **kwargs):
    if not hasattr(Singleton, "_instance"):
        with Singleton._instance_lock:
            if not hasattr(Singleton, "_instance"):
                Singleton._instance = object.__new__(cls)  
    return Singleton._instance

obj1 = Singleton()
obj2 = Singleton()
print(obj1,obj2)

def task(arg):

obj = Singleton()
print(obj)

for i in range(10):

t = threading.Thread(target=task,args=[i,])
t.start()

基于metaclass方式来实现
import threading

class SingletonType(type):

_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
    if not hasattr(cls, "_instance"):
        with SingletonType._instance_lock:
            if not hasattr(cls, "_instance"):
                cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
    return cls._instance

class Foo(metaclass=SingletonType):

def __init__(self,name):
    self.name = name

obj1 = Foo("name")
obj2 = Foo("name")
print(obj1,obj2)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43679.html

相关文章

  • Spring IOC知识点一网打尽!

    摘要:使用的好处知乎的回答不用自己组装,拿来就用。统一配置,便于修改。 前言 只有光头才能变强 回顾前面: 给女朋友讲解什么是代理模式 包装模式就是这么简单啦 单例模式你会几种写法? 工厂模式理解了没有? 在刷Spring书籍的时候花了点时间去学习了单例模式和工厂模式,总的来说还是非常值得的! 本来想的是刷完《Spring 实战 (第4版)》和《精通Spring4.x 企业应用开发实战》...

    djfml 评论0 收藏0
  • 设计模式单例模式

    摘要:单例模式关注的重点私有构造器线程安全延迟加载序列化和反序列化安全反射攻击安全相关设计模式单例模式和工厂模式工厂类可以设计成单例模式。 0x01.定义与类型 定义:保证一个类仅有一个实例,并提供一个全局访问点 类型:创建型 UML showImg(https://segmentfault.com/img/bVbtDJ2?w=402&h=268); 单例模式的基本要素 私有的构造方...

    陆斌 评论0 收藏0
  • Java设计模式优化-单例模式

    摘要:单例模式概述单例模式是一种对象创建模式,用于产生一个类的具体事例。所以解决了线程安全问题参考失效原因和解决方案中单例模式的缺陷及单例的正确写法懒汉式静态内部类私有构造器获取单例的方法静态内部类持有单例作为静态属性。 单例模式概述 单例模式是一种对象创建模式,用于产生一个类的具体事例。使用单例模式可以确保整个系统中单例类只产生一个实例。有下面两大好处: 对于频繁创建的对象,节省初第一...

    eccozhou 评论0 收藏0
  • 又被面试官问设计模式了,我真的是

    摘要:面试官要不你来手写下单例模式呗候选者单例模式一般会有好几种写法候选者饿汉式简单懒汉式在方法声明时加锁双重检验加锁进阶懒汉式静态内部类优雅懒汉式枚举候选者所谓饿汉式指的就是还没被用到,就直接初始化了对象。面试官:我看你的简历写着熟悉常见的设计模式,要不你来简单聊聊你熟悉哪几个吧?候选者:常见的工厂模式、代理模式、模板方法模式、责任链模式、单例模式、包装设计模式、策略模式等都是有所了解的候选者:...

    不知名网友 评论0 收藏0
  • 23种设计模式

    摘要:抽象工厂模式多个抽象产品类,个抽象产品类可以派生出多个具体产品类。用了工厂方法模式,你替换生成键盘的工厂方法,就可以把键盘从罗技换到微软。好处避免频繁创建对象,节省系统开销,减轻压力。 总体分为3大类:创建型模式 (5种):工厂方法、抽象工厂、单例、建造者、原型结构型模式(7种):适配器、装饰器、代理、外观、桥接、组合、享元行为型模式(11种):策略、模板方法、观察者、迭代子、责任链、...

    xiaokai 评论0 收藏0

发表评论

0条评论

chemzqm

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<