一、简单工厂模式
其他语言的实现:
''' 抽象运算类,以及具体运算类:加、减、乘、除 ''' 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