抽象工厂概念

       提供一个创建一系列相关或者相互依赖对象的接口。而无需指定它们具体的类。。 。。可能还是一头雾水。学习完下面两个案例,你就清楚了。

案例1

         想像一下,我们现在要研究一款老少皆宜的游戏。 少儿登录后的游戏场景是:主人公是青蛙,喜欢吃虫子。大人登录后的游戏场景是:男巫战怪兽。 在运行时,基于用户输入,决定该创建那个游戏并运行。  游戏的创建部分由一个抽象工厂维护。

# 小孩子的模式
class Frog:          # 青蛙类 可以设置名字
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return self.name
    def interact_with(self, obstacle):
        print('{} the Frog encounter {} and {}'.format(self, obstacle, obstacle.action()))
class Bug:         # 虫子类  
    def __str__(self):
        return 'a bug'
    def action(self):
        return 'eats it'

class FrogWorld:     # 孩子的游戏场景
    def __init__(self, name):
        print(self)
        self.player_name = name

    def __str__(self):
        return '\n\n\t------Frog World-----'

    def make_character(self):
        return Frog(self.player_name)

    def make_obstacle(self):
        return Bug()


# 大人的模式
class Wizard:      # 巫师类   可以指定名字
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return self.name
    def interact_with(self, obstacle):
        print('{} the Wizard battles against {} and {}!'.format(self, obstacle, obstacle.action()))

class Ork:     # 怪兽类  
    def __str__(self):
        return 'an evil ork'
    def action(self):
        return 'kills it'

class WizardWorld:     # 大人们的游戏场景
    def __init__(self, name):
        print(self)
        self.player_name = name

    def __str__(self):
        return '\n\n\t------Wizard World-----'
    def make_character(self):
        return Wizard(self.player_name)
    def make_obstacle(self):
        return Ork()

class GameEnvironment:     # 所谓的抽象工厂:就是根据我们传入的factory对象,然后开启不同生成不同游戏中的任务
    def __init__(self, factory):
        self.hero = factory.make_character()
        self.obstacle = factory.make_obstacle()

    def play(self):
        self.***teract_with(self.obstacle)

def validate_age(name):    # 设置一个年龄的判断。。看是小孩还是大人
    try:
        age = input('Welcome {}. How old are you?'.format(name))
        age = int(age)
    except ValueError as err:
        print('Age {} is invalid, please try again-----'.format(age))
        return (False, age)
    return (True, age)

if __name__ == '__main__':
    name = input('Hello. What is your name?')
    valid_input = False
    while not valid_input:
        valid_input, age = validate_age(name)
    game = FrogWorld if age < 18 else WizardWorld   # 根据年龄的不同生成不同的对象
    environment = GameEnvironment(game(name))
    environment.play()

             解析: 上述代码中GameEnvironment类起的就是一个抽象工厂的作用 。。 我们根据年龄的不同,生成不同游戏场景的实例。然后将实例传给GameEnvironment ,让他生成游戏中不同的人物。最后让青蛙打虫子等。。

           上述代码的输出结果:

       

案例2:

      我们现在有两种数据库, 分别为Sqlserver和Access数据库。。这两个数据库中分别有两张表,分别为用户表,部门表。。我们想要做的就是可以随便切换数据库 ,进行当前数据库中数据的修改。

# 针对不同数据库,我们创建不同的访问用户
from abc import ABCMeta, abstractmethod

# 用户表
class IUser(metaclass=ABCMeta):    # 相当于接口,这个代表一张表
    @abstractmethod
    def insert(self):    # 在数据库中给用户表插入数据
        pass
    @abstractmethod
    def getUser(self):   # 在数据库中获取用户表的记录
        pass

# 在Sqlserver数据库创建用户表
class SqlserverUser(IUser):

    def insert(self):
        print("在Sqlserver的用户表中插入一条数据咯")

    def getUser(self):
        print("在Sqlserver中得到一条用户表的记录")

# 在Access数据库创建用户表
class AccessUser(IUser):

    def insert(self):
        print("在Access的用户表中插入一条数据咯")

    def getUser(self):
        print("在Access中得到一条用户表的记录")


# 再搞一个表   部门表
class IDepartment(metaclass=ABCMeta):
    @abstractmethod
    def insert(self):  # 在数据库中为部门表插入记录
        pass

    @abstractmethod
    def getDepartment(self):  # 获取部门表中的记录
        pass

# 在Sqlserver数据库创建用户表
class SqlserverDepartment(IDepartment):
    def insert(self):
        print("在Sqlserver的部门表中插入一条数据咯")

    def getDepartment(self):
        print("在Sqlserver中得到一条部门表的记录")

# 在Access数据库创建用户表
class AccessDepartment(IDepartment):
    def insert(self):
        print("在Access的部门表中插入一条数据咯")

    def getDepartment(self):
        print("在Access中得到一条部门表的记录")

# 抽象工厂
class IFactory(metaclass=ABCMeta):

    @abstractmethod
    def createUser(self):    # 创建用户表
        pass

    @abstractmethod
    def createDepartment(self):   # 创建部门表
        pass

class SqlServerFactory(IFactory):

    def createUser(self):
        return SqlserverUser()

    def createDepartment(self):
        return SqlserverDepartment()

class AccessFactory(IFactory):

    def createUser(self):
        return AccessUser()

    def createDepartment(self):
        return AccessDepartment()

def caozuo_user(factory):    # 操作用户表
    iu = factory.createUser()
    iu.insert()
    iu.getUser()

def caozuo_department(factory):   # 操作部门表
    ide = factory.createDepartment()
    ide.insert()
    ide.getDepartment()


if __name__ == '__main__':

    print("对Access数据库的操作。")
    factory = AccessFactory()  # 在这里换数据库
    caozuo_user(factory)   # 操作用户表
    caozuo_department(factory)  # 操作部门表
    print('\n')

    print("对SqlServer数据库的操作。")
    factory = SqlServerFactory()  # 在这里换数据库
    caozuo_user(factory)  # 操作用户表
    caozuo_department(factory)  # 操作部门表

    这里的SqlServerFactory和AccessFactory相当于我们第一个例子中的FrogWorld和WizardWorld 针对不同的情况,创建不同的对象。。第二个例子还可以再进行封装。这里我就不做了。。大家仿照第一个例子进行改进。

  输出结果: