• 一起来学设计模式-----创建型模式之抽象工厂


           学习了简单工厂,工厂方法模式,那什么是抽象工厂呢?工厂方法模式是在超类(IFactory)中定义一个工厂的抽象接口(CreateOperation),然后由子类负责创建具体对象;而抽象工厂则是维护一个产品家族,由子类定义产品被产生的方法,客户根据超类的接口开发。目前简单的理解,抽象工厂更多的就是基于多种产品的抽象和对象的创建。

         假设系统里有一个用户表,需求是插入和选择用户时根据用户的需求,可以保存在mysql 数据库或者Access数据库中,这时用工厂方法模式应该怎么样实现呢?

         首先使用面向对象的概念进行业务抽象,用户是一个类,使用mysql操作用户表是一个具体实践类,使用Access操作用户表是一个具体的实践类,操作类可以抽象成一个接口IUser类,根据工厂方法模式,则每个实践类都需要一个实际工厂是实例化,则需要2个具体工厂,这2个具体的工厂又能抽象一个接口IFactory类。客户端就可以根据实际情况,选择使用具体的工厂,创造出具体的类,操作user表。代码实现如下:

    
    
    from abc import ABCMeta, abstractmethod


    class User:
    def __int__(self,id):
    self.id = id

    class IUser:
    @abstractmethod
    def InsertUser(self,user):
    pass

    @abstractmethod
    def GetUser(self,id):
    pass

    class IFactory:
    @abstractmethod
    def CreateUser(self):
    pass


    class AccessUser(IUser):
        def InsertUser(self,user):
            print ("在access中为User表增加一条记录")
    
        def GetUser(self,id):
            print ("在access中为User表查询一条记录")
    
    class MysqlUser(IUser):
        def InsertUser(self,user):
            print ("在mysql中为User表增加一条记录")
    
        def GetUser(self,id):
            print ("在mysql中为User表查询一条记录")

    class MysqlFactory(IFactory):
    def CreateUser(self):
    return MysqlUser()

    class AccessFactory(IFactory):
    def CreateUser(self):
    return AccessUser()

    客户端调用的代码如下:

    if __name__ == '__main__':
         user = User()
         factory = MysqlFactory()
         iu = factory.CreateUser()
         iu.InsertUser(user)
         iu.GetUser(1)

    UML类图:

     

        如果此时,再加一个Department表,业务类似User一样的增加,在工厂类中,增加工厂创建实例对象的方法即可。则UML类图应该是下面这样的:

     

            代码实现如下:

    class User:
        def __int__(self,id):
            self.id = id
    
    class Department:
        def __int__(self,depName):
            self.depName = depName
    
    
    class IUser:
        @abstractmethod
        def InsertUser(self,user):
            pass
    
        @abstractmethod
        def GetUser(self,id):
            pass
    
    
    class IDepartment:
        @abstractmethod
        def InsertDepartment(self,dep):
            pass
    
        @abstractmethod
        def GetDepartment(self,depname):
            pass
    
    class IFactory:
        @abstractmethod
        def CreateUser(self):
            pass
    
        @abstractmethod
        def CreateDepartment(self):
            pass
    
    class AccessUser(IUser):
        def InsertUser(self,user):
            print ("在access中为User表增加一条记录")
    
        def GetUser(self,id):
            print ("在access中为User表查询一条记录")
    
    class MysqlUser(IUser):
        def InsertUser(self,user):
            print ("在mysql中为User表增加一条记录")
    
        def GetUser(self,id):
            print ("在mysql中为User表查询一条记录")
    
    class AccessDepartment(IDepartment):
        def InsertDepartment(self,dep):
            print ("在access中为Department表增加一条记录")
    
        def GetDepartment(self,id):
            print ("在access中为Department表查询一条记录")
    
    class MysqlDepartment(IDepartment):
        def InsertDepartment(self,dep):
            print ("在mysql中为Department表增加一条记录")
    
        def GetDepartment(self,id):
            print ("在mysql中为Department表查询一条记录")
    class MysqlFactory(IFactory):
        def CreateUser(self):
            return MysqlUser()
    
        def CreateDepartment(self):
            return MysqlDepartment()
    
    class AccessFactory(IFactory):
        def CreateUser(self):
            return AccessUser()
    
        def CreateDepartment(self):
            return AccessDepartment()

    客户端代码如下:

    if __name__ == '__main__':
         user = User()
         factory = MysqlFactory()
         iu = factory.CreateUser()
         iu.InsertUser(user)
         iu.GetUser(1)
    
         dep = Department()
         asFactory = AccessFactory()
         idep = asFactory.CreateDepartment()
         idep.InsertDepartment(dep)
         idep.GetDepartment('loleina')

           这么一看,就已经实现了抽象工厂方法,工厂方法模式是定义一个用于创建对象的接口(IFactory),让子类(MysqlFactory,AccessFactory)去决定实例化哪一个类。而抽象工厂,是提供一个创建一系列相关或相互依赖对象的接口(IFactory内可以有多个产品的抽象),而无须指定它们的具体的类。

         抽象工厂最大的好处就是,客户端可以根据自己的需求,从不同的工厂中获取不同的产品对象,从而得到不同的产品。但是这个模式实际也是有很多缺点的,比如思考下此时加入一个新的表,要改动哪些呢?

    下面以UML类图变化为例。灰色部分表示需要修改的地方。工厂类就得全部修改一遍。。。

    相比如果增加一个工厂,代价是相对还少点。

            实际在真正的项目使用上,根据我进鹅厂看了这么多的业务代码经验,这类设计模式一般是不会被才采用到的,一般都是使用反射 + 配置文件(DB配置)+ 简单工厂来实现,这样增加产品类型时,只需要增加响应的产品,增加相关的配置,而无须修改任何代码。使用这个思路修改这个例子。

     代码实现如下:

    class DateAccess:
        @staticmethod
        def CreateUser():
    #DBType和DBTableName来自于配置文件或者DB配置 DBType
    = 'Mysql' DBTableUser = 'User' instanceName = DBType +DBTableUser return eval(instanceName)() @staticmethod def CreatDepartment(): DBType = 'Mysql' DBTableDep = 'Department' instanceName = DBType + DBTableDep return eval(instanceName)()

    客户端调用如下:

    if __name__ == '__main__':
         user = User()
         iu = DateAccess.CreateUser()
         iu.InsertUser(user)
         iu.GetUser(1)
    
         dep = Department()
         idep =DateAccess.CreatDepartment()
         idep.InsertDepartment(dep)
         idep.GetDepartment('test')
  • 相关阅读:
    Win8metro外包团队:专业承接Windows 8 metro应用外包,基于HTML5、Silverlight、.NET均可
    WPF性能优化经验总结和整理综合帖
    WPF外包—WPF案例分享—WPF实现的又一个阅读器MSDN Reader
    中国已成为亚太区企业首选的外包基地
    Acer北京维修站汇总(今天电脑坏了去维修,顺便分享一下)
    WPF外包公司——北京动点飞扬软件联系方式和官方博客地址
    微软首推msnNOW服务 网络社交化风暴愈演愈烈
    WPF外包就找北京动点飞扬软件:WPF 4.5探秘之三 Dispatcher的新方法
    微软发布Windows 8标志:彰显创新回归本源(图)
    中国软件产业发展全国数据对比
  • 原文地址:https://www.cnblogs.com/loleina/p/7397067.html
Copyright © 2020-2023  润新知