zoukankan      html  css  js  c++  java
  • 设计模式----创建型设计模式【简单工厂、工厂方法、抽象工厂】

    一、简单工厂模式

    其他语言的实现:

    '''
    抽象运算类,以及具体运算类:加、减、乘、除
    '''
    class Operation:  # 抽象运算类
        numberA = 0
        numberB = 0
        def get_result(self):
            pass
    class OperationAdd(Operation):  # 加法类
        def get_result(self):
            return self.numberA + self.numberB
    class OperationSub(Operation):  # 减法类
        def get_result(self):
            return self.numberA - self.numberB
    class OperationMul(Operation):  # 乘法类
        def get_result(self):
            return self.numberA * self.numberB
    class OperationDiv(Operation):  # 除法类
        def get_result(self):
            return self.numberA / self.numberB
    class OperationFactory:
        @staticmethod
        def create_operate(operate_name):
            oper = None
            if operate_name == '+':
                oper = OperationAdd()
            elif operate_name == '-':
                oper = OperationSub()
            elif operate_name == '*':
                oper = OperationMul()
            elif operate_name == '/':
                oper = OperationDiv()
            return oper
    
    if __name__ == '__main__':
        oper = OperationFactory.create_operate('+')
        oper.numberA = 1
        oper.numberB = 2
        result = oper.get_result()
        print(result)
    简单工厂模式

    Python版:

    二、工厂方法模式

    其他语言版

    '''
    抽象运算类,以及具体运算类:加、减、乘、除
    '''
    class Operation:  # 抽象运算类
        numberA = 0
        numberB = 0
        def get_result(self):
            pass
    class OperationAdd(Operation):  # 加法类
        def get_result(self):
            return self.numberA + self.numberB
    class OperationSub(Operation):  # 减法类
        def get_result(self):
            return self.numberA - self.numberB
    class OperationMul(Operation):  # 乘法类
        def get_result(self):
            return self.numberA * self.numberB
    class OperationDiv(Operation):  # 除法类
        def get_result(self):
            return self.numberA / self.numberB
    
    '''
    抽象工厂类,以及具体工厂类:加法工厂、减法工厂、乘法工厂、除法工厂
    '''
    class IFactory:
        def create_operate(self):
            pass
    class AddFactory(IFactory):
        def create_operate(self):
            return OperationAdd()
    class SubFactory(IFactory):
        def create_operate(self):
            return OperationSub()
    class MulFactory(IFactory):
        def create_operate(self):
            return OperationMul()
    class DivFactory(IFactory):
        def create_operate(self):
            return OperationDiv()
    
    if __name__ == '__main__':
        oper_factory = AddFactory()
        oper = oper_factory.create_operate()
        oper.numberA = 1
        oper.numberB = 2
        result = oper.get_result()
        print(result)
    工厂方法模式
    '''
    简单工厂与工厂方法的区别:
    如果要实现新加一个运算类
    简单工厂需要:1、加一个运算类 2、加一个if分支进行判断
    工厂方法需要:1、加一个运算类 2、加一个该运算的工厂类 3、main方法需要改工厂类(要修改代码)
    感悟:
    简单工厂的获取对象类型可以写入配置文件,但是要修改类里的代码,不太好。工厂方法是新增类,比较好,但是获取的对象类型在客户端写死了。
    工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你想要加功能,使用简单工厂需要修改工厂类,而使用工厂方法是修改客户端
    '''

    Python版:

    #!/usr/bin/env python3
    # Copyright © 2012-13 Qtrac Ltd. All rights reserved.
    # This program or module is free software: you can redistribute it
    # and/or modify it under the terms of the GNU General Public License as
    # published by the Free Software Foundation, either version 3 of the
    # License, or (at your option) any later version. It is provided for
    # educational purposes and is distributed in the hope that it will be
    # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    # General Public License for more details.
    
    import io
    import itertools
    import os
    import sys
    import tempfile
    import unicodedata
    
    
    DRAUGHT, PAWN, ROOK, KNIGHT, BISHOP, KING, QUEEN = ("DRAUGHT", "PAWN",
            "ROOK", "KNIGHT", "BISHOP", "KING", "QUEEN")
    BLACK, WHITE = ("BLACK", "WHITE")
    
    
    def main():
        checkers = CheckersBoard()
        print(checkers)
    
        chess = ChessBoard()
        print(chess)
    
        if sys.platform.startswith("win"):
            filename = os.path.join(tempfile.gettempdir(), "gameboard.txt")
            with open(filename, "w", encoding="utf-8") as file:
                file.write(sys.stdout.getvalue())
            print("wrote '{}'".format(filename), file=sys.__stdout__)
    
    
    if sys.platform.startswith("win"):
        def console(char, background):
            return char or " "
        sys.stdout = io.StringIO()
    else:
        def console(char, background):
            return "x1B[{}m{}x1B[0m".format(
                    43 if background == BLACK else 47, char or " ")
    
    
    class AbstractBoard:
    
        def __init__(self, rows, columns):
            self.board = [[None for _ in range(columns)] for _ in range(rows)]
            self.populate_board()
    
    
        def populate_board(self):
            raise NotImplementedError()
    
    
        def __str__(self):
            squares = []
            for y, row in enumerate(self.board):
                for x, piece in enumerate(row):
                    square = console(piece, BLACK if (y + x) % 2 else WHITE)
                    squares.append(square)
                squares.append("
    ")
            return "".join(squares)
    
    
    class CheckersBoard(AbstractBoard):
    
        def __init__(self):
            self.populate_board()
    
    
        def populate_board(self): # Thanks to Doug Hellmann for the idea!
            def black():
                return create_piece(DRAUGHT, BLACK)
            def white():
                return create_piece(DRAUGHT, WHITE)
            rows = ((None, black()), (black(), None), (None, black()),
                    (black(), None),            # 4 black rows
                    (None, None), (None, None), # 2 blank rows
                    (None, white()), (white(), None), (None, white()),
                    (white(), None))            # 4 white rows
            self.board = [list(itertools.islice(
                itertools.cycle(squares), 0, len(rows))) for squares in rows]
    
    
    class ChessBoard(AbstractBoard):
    
        def __init__(self):
            super().__init__(8, 8)
    
    
        def populate_board(self):
            for row, color in ((0, BLACK), (7, WHITE)):
                for columns, kind in (((0, 7), ROOK), ((1, 6), KNIGHT),
                        ((2, 5), BISHOP), ((3,), QUEEN), ((4,), KING)):
                    for column in columns:
                        self.board[row][column] = create_piece(kind, color)
            for column in range(8):
                for row, color in ((1, BLACK), (6, WHITE)):
                    self.board[row][column] = create_piece(PAWN, color)
    
    
    def create_piece(kind, color):   # 根据棋子的颜色(白、黑)和类型(象棋、跳棋)生成相应对象
        color = "White" if color == WHITE else "Black"
        name = {DRAUGHT: "Draught", PAWN: "ChessPawn", ROOK: "ChessRook",
                KNIGHT: "ChessKnight", BISHOP: "ChessBishop",
                KING: "ChessKing", QUEEN: "ChessQueen"}[kind]
        return globals()[color + name]()
    
    
    class Piece(str):
    
        __slots__ = ()
    
    
    for code in itertools.chain((0x26C0, 0x26C2), range(0x2654, 0x2660)):  # 动态创建“棋子”类型
        char = chr(code)
        name = unicodedata.name(char).title().replace(" ", "")
        if name.endswith("sMan"):
            name = name[:-4]
        new = (lambda char: lambda Class: Piece.__new__(Class, char))(char)
        new.__name__ = "__new__"
        Class = type(name, (Piece,), dict(__slots__=(), __new__=new))
        globals()[name] = Class
    
    
    if __name__ == "__main__":
        main()
    生成棋盘和棋子

    三、抽象工厂模式:

    其他语言版

    '''
    数据库表
    '''
    class User:  # 用户表
        id = None
        name = None
    
    class Department:  # 部门表
        id = None
        name = None
    '''
    数据库表对应的抽象操作类
    '''
    class IDepartment:
        def insert(self, dept):
            pass
        def get_dept(self, id):
            pass
    class IUser:
        def insert(self, user):
            pass
        def get_user(self, id):
            pass
        def del_user(self, id):
            pass
    '''
    数据库表对应的实体操作类:SQLServer和Access
    '''
    class SqlserverDepartment(IDepartment):
        def insert(self, dept):
            print('在SQLServer中给Department表增加一条记录')
        def get_dept(self, id):
            print('在SQLServer中根据ID得到Department表的一条记录')
    class SqlserverUser(IUser):
        def insert(self, user):
            print('在SQLServer中给User表增加一条记录')
        def get_user(self, id):
            print('在SQLServer中根据ID得到User表的一条记录')
        def del_user(self, id):
            print('在SQLServer中根据ID删除User表的一条记录')
    
    class AccessDepartment(IDepartment):
        def insert(self, dept):
            print('在Access中给Department表增加一条记录')
        def get_dept(self, id):
            print('在Aceess中根据ID得到Department表的一条记录')
    class AccessUser(IUser):
        def insert(self, user):
            print('在Access中给User表增加一条记录')
        def get_user(self, id):
            print('在Access中根据ID得到User表的一条记录')
        def del_user(self, id):
            print('在Access中根据ID删除User表的一条记录')
    '''
    抽象工厂类:用于获取表的实体操作类对象
    '''
    class IFactory:
        def create_user(self):
            pass
        def create_department(self):
            pass
    '''
    实体操作类:用于获取表的实体操作类对象
    '''
    class SqlserverFactory(IFactory):
        def create_user(self):
            return SqlserverUser()
        def create_department(self):
            return SqlserverDepartment()
    
    class AccessFactory(IFactory):
        def create_user(self):
            return AccessUser()
        def create_department(self):
            return AccessDepartment()
    
    if __name__ == '__main__':
        user = User()
        dept = Department()
        factory = SqlserverFactory()  # 只需确定实例化哪一个数据库访问对象给factory
        iu = factory.create_user()
        iu.insert(user)
        iu.get_user(1)
        iu.del_user(1)
        id = factory.create_department()
        id.insert(dept)
        id.get_dept(1)
    
    '''
    在SQLServer中给User表增加一条记录
    在SQLServer中根据ID得到User表的一条记录
    在SQLServer中根据ID删除User表的一条记录
    在SQLServer中给Department表增加一条记录
    在SQLServer中根据ID得到Department表的一条记录
    '''
    原始的抽象工厂
    抽象工厂模式最大的好处是易于交易产品序列:此处是SQLServer系列和Access系列
    如果要增加一张新表Project,需要增加
    Project类、IProject抽象操作类、SqlServerProject(IProject)具体操作类、AccessProject(IProject)具体操作类
    还需要更改
    IFactory类、SqlserverFactory(IFactory)类、AccessFactory(IFactory)类
    这样会很麻烦。
    '''
    数据库表
    '''
    class User:  # 用户表
        id = None
        name = None
    
    class Department:  # 部门表
        id = None
        name = None
    '''
    数据库表对应的抽象操作类
    '''
    class IDepartment:
        def insert(self, dept):
            pass
        def get_dept(self, id):
            pass
    class IUser:
        def insert(self, user):
            pass
        def get_user(self, id):
            pass
        def del_user(self, id):
            pass
    '''
    数据库表对应的实体操作类:SQLServer和Access
    '''
    class SqlserverDepartment(IDepartment):
        def insert(self, dept):
            print('在SQLServer中给Department表增加一条记录')
        def get_dept(self, id):
            print('在SQLServer中根据ID得到Department表的一条记录')
    class SqlserverUser(IUser):
        def insert(self, user):
            print('在SQLServer中给User表增加一条记录')
        def get_user(self, id):
            print('在SQLServer中根据ID得到User表的一条记录')
        def del_user(self, id):
            print('在SQLServer中根据ID删除User表的一条记录')
    
    class AccessDepartment(IDepartment):
        def insert(self, dept):
            print('在Access中给Department表增加一条记录')
        def get_dept(self, id):
            print('在Aceess中根据ID得到Department表的一条记录')
    class AccessUser(IUser):
        def insert(self, user):
            print('在Access中给User表增加一条记录')
        def get_user(self, id):
            print('在Access中根据ID得到User表的一条记录')
        def del_user(self, id):
            print('在Access中根据ID删除User表的一条记录')
    
    '''
    简单工厂改造抽象工厂:可使用反射
    '''
    class DataAccess:
        db = 'Access'   # 在此处设置数据库类型
        @staticmethod
        def create_user():
            iuser = None
            if DataAccess.db == 'Access':
                iuser = AccessUser()
            elif DataAccess.db == 'SqlServer':
                iuser = SqlserverUser()
            return iuser
        @staticmethod
        def create_department():
            idepat = None
            if DataAccess.db == 'Access':
                idepat = AccessDepartment()
            elif DataAccess.db == 'SqlServer':
                idepat = SqlserverDepartment()
            return idepat
    
    if __name__ == '__main__':
        user = User()
        dept = Department()
        iu = DataAccess.create_user()
        iu.insert(user)
        iu.get_user(1)
        iu.del_user(1)
        id = DataAccess.create_department()
        id.insert(dept)
        id.get_dept(1)
    
    '''
    在SQLServer中给User表增加一条记录
    在SQLServer中根据ID得到User表的一条记录
    在SQLServer中根据ID删除User表的一条记录
    在SQLServer中给Department表增加一条记录
    在SQLServer中根据ID得到Department表的一条记录
    '''
    简单工厂改造后的抽象工厂

    Python版: 不能写到配置文件

    1.使用classmethod方法,将各自的类放到各自的工厂

    2.使用cls.User  cls.Department通用名称,以便重用该方法

    '''
    数据库表
    '''
    class User:  # 用户表
        def __init__(self, id=None, name=None):
            self.id = None or id
            self.name = None or name
    
    class Department:  # 部门表
        def __init__(self, id=None, name=None):
            self.id = None or id
            self.name = None or name
    '''
    数据库表对应的抽象操作类
    '''
    import abc
    class IDepartment(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def insert(self, dept):
            pass
        @abc.abstractmethod
        def get_dept(self, id):
            pass
    class IUser(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def insert(self, user):
            pass
        @abc.abstractmethod
        def get_user(self, id):
            pass
        @abc.abstractmethod
        def del_user(self, id):
            pass
    '''
    数据库表对应的实体操作类:SQLServer和Access
    '''
    class SqlserverFactory:
        @classmethod
        def create_user(cls):
            return cls.User()
        @classmethod
        def create_department(cls):
            return cls.Department()
    
        class Department(IDepartment):
            def insert(self, dept):
                print('在SQLServer中给Department表增加一条记录')
            def get_dept(self, id):
                print('在SQLServer中根据ID得到Department表的一条记录')
        class User(IUser):
            def insert(self, user):
                print('在SQLServer中给User表增加一条记录')
            def get_user(self, id):
                print('在SQLServer中根据ID得到User表的一条记录')
            def del_user(self, id):
                print('在SQLServer中根据ID删除User表的一条记录')
    
    class AccessFactory(SqlserverFactory):
        class Department(IDepartment):
            def insert(self, dept):
                print('在Access中给Department表增加一条记录')
            def get_dept(self, id):
                print('在Aceess中根据ID得到Department表的一条记录')
        class User(IUser):
            def insert(self, user):
                print('在Access中给User表增加一条记录')
            def get_user(self, id):
                print('在Access中根据ID得到User表的一条记录')
            def del_user(self, id):
                print('在Access中根据ID删除User表的一条记录')
    
    
    if __name__ == '__main__':
        user = User()
        dept = Department()
        # iu = AccessFactory.create_user()
        iu = globals()['AccessFactory'].create_user()  # 动态,可写入配置文件
        iu.insert(user)
        iu.get_user(1)
        iu.del_user(1)
    
        # id = AccessFactory.create_department()
        id = globals()['AccessFactory'].create_department()  # 动态,可写入配置文件
        id.insert(dept)
        id.get_dept(1)
    
    '''
    在Access中给User表增加一条记录
    在Access中根据ID得到User表的一条记录
    在Access中根据ID删除User表的一条记录
    在Access中给Department表增加一条记录
    在Aceess中根据ID得到Department表的一条记录
    '''
    
    

    1

    12

    1

  • 相关阅读:
    57.适合自己的就是最好的
    45.懂得放弃
    ASP.NET碎知识点
    app性能测试理论基础一篇
    记一次踩坑docker+Jenkins+python3.6.8+gitee
    IT测试人从浓密到稀疏的的发量之路
    一天基本上没什么效率
    如此复杂的心情,如此失落的感觉…
    String.Replace 方法 (String, String)
    《见与不见》原题《班扎古鲁白玛的沉默》 作者:扎西拉姆·多多
  • 原文地址:https://www.cnblogs.com/staff/p/11642950.html
Copyright © 2011-2022 走看看