举个例子: 有个汽车生产工厂,最开始规模比较小,轿车和SUV啊客车等在一个车间里面,你要哪个车就对这个工厂说,我要xx车,这个工厂就出来一个这个车。这就是简单工厂
简单工厂:只有一个抽象,由工厂去获得抽象类的具体对象,工厂内的方法可以看做静态方法
一段时间的运行效益越来越好,要把这三条流水线分开,就分出了三个工厂,轿车工厂,SUV工厂和客车工厂。
工厂方法:有两个抽象,工厂的抽象和具体类的抽象。
工厂方法和简单工厂相比,
1、工厂方法更好的实现了开闭原则,要增加类只需要增加代码,简单工厂会改类里面的代码,会增加分支判断
2、工厂方法把简单工厂的if else分支判断交给了客户端
抽象工厂:拿数据库的例子来说,有user表操作接口(包括SQL实现,和access实现)有dept表操作接口(包括SQL实现和access实现) 抽象工厂类(获取user表操作,获取dept表操作) 具体实现类(SQL工厂access工厂)。
抽象工厂的客户端需要知道有哪些工厂可以选择,先new出来具体的工厂,再用具体的工厂获取具体的对象。
抽象工厂这个例子里面有两种具体的表(user和dept),两个处理方式(SQL和access)。 按处理方式来分成两种工厂,每个工厂都有两种抽象的表处理, 每个表处理是一种抽象。
简单工厂模式:
老王汽车厂刚成立的时候,只有一个工厂,既生产雷凌Levin,也生产汉兰达Highlander。
客户端代码:
package simplefactory; public class Main { public static void main(String[] args) { Factory f = new Factory(); TrafficTool levin = f.createLevin(); TrafficTool highlander = f.createHighlander(); levin.run(); highlander.run(); } }
Factory类:
package simplefactory; public class Factory { /** * 生产雷凌 * @return */ public TrafficTool createLevin(){ return new Levin(); } /** * 生产汉兰达 * @return */ public TrafficTool createHighlander(){ return new Highlander(); } }
Levin具体类--继承TrafficTool抽象类
package simplefactory; public class Levin extends TrafficTool { @Override public void run() { System.out.println("雷凌....run"); } }
Highlander具体类--继承TrafficTool抽象类
package simplefactory; public class Highlander extends TrafficTool { @Override public void run() { System.out.println("汉兰达...run"); } }
TrafficTool抽象类:
package simplefactory; public abstract class TrafficTool { public abstract void run(); }
工厂方法模式
经过一段时间经营,老王汽车厂订单大大增加,一个工厂已经不够用了,现在要给雷凌和汉兰达单独搞个工厂
客户端:
package factorymethod; public class Main { public static void main(String[] args) { Factory highlanderFactory = new HighlanderFactory(); TrafficTool highlander = highlanderFactory.create(); highlander.run(); Factory levinFactory = new LevinFactory(); TrafficTool levin = levinFactory.create(); levin.run(); //工厂方法优点:容易扩展新产品。例如:要再增加一个车型卡罗拉,只需要增加Corolla类,CorollaFactory类 } }
抽象工厂类:Factory
package factorymethod; public abstract class Factory { public abstract TrafficTool create(); }
具体工厂类:HighlanderFactory
package factorymethod; public class HighlanderFactory extends Factory{ @Override public Highlander create(){ return new Highlander(); } }
具体工厂类:LevinFactory
package factorymethod; public class LevinFactory extends Factory{ @Override public Levin create(){ return new Levin(); } }
抽象产品类:TrafficTool
package factorymethod; public abstract class TrafficTool { public abstract void run(); }
具体产品类:Levin
package factorymethod; public class Levin extends TrafficTool{ @Override public void run(){ System.out.println("雷凌 running..."); } }
具体产品类:Highlander
package factorymethod; public class Highlander extends TrafficTool { @Override public void run(){ System.out.println("汉兰达 running..."); } }
抽象工厂:
为了更好地满足客户,现在,老王不仅要造车,还要给自己的车造配套的装饰品,雷凌装饰品 ,汉兰达装饰品
客户端:
package abstractfactory; public class Main { public static void main(String[] args) { Factory levinFactory = new LevinFactory(); TrafficTool levin = levinFactory.createTrafficTool(); Decorator levinDecorator = levinFactory.createDecorator(); levin.run(); levinDecorator.decorate(); Factory highlanderFactory = new HighlanderFactory(); TrafficTool highlander = highlanderFactory.createTrafficTool(); Decorator highlanderDecorator = highlanderFactory.createDecorator(); highlander.run(); highlanderDecorator.decorate(); // 扩展产品族比较方便。例如:老王还想搞一个卡罗拉厂(生产卡罗拉和装饰品)就比较方便,只需要加Corolla类、CorollaDecorator类、CorollaFactory类即可 } }
抽象工厂类:Factory
package abstractfactory; public abstract class Factory { //生产交通工具 public abstract TrafficTool createTrafficTool(); //生产交通工具对应的装饰品 public abstract Decorator createDecorator(); }
抽象交通工具类:TrafficTool
package abstractfactory; /** * 抽象类:交通工具 */ public abstract class TrafficTool { public abstract void run(); }
抽象装饰品类:Decorator
package abstractfactory; /** * 抽象类:装饰品 */ public abstract class Decorator { public abstract void decorate(); }
具体类:LevinFactory、Levin、LevinDecorator
package abstractfactory; public class LevinFactory extends Factory { @Override public TrafficTool createTrafficTool() { return new Levin(); } @Override public Decorator createDecorator() { return new LevinDecorator(); } } class Levin extends TrafficTool { @Override public void run() { System.out.println("雷凌..run..."); } } class LevinDecorator extends Decorator { @Override public void decorate() { System.out.println("雷凌的装饰品..."); } }
具体类:HighlanderFactory、Highlander、HighlanderDecorator
package abstractfactory; public class HighlanderFactory extends Factory { @Override public TrafficTool createTrafficTool() { return new Highlander(); } @Override public Decorator createDecorator() { return new HighlanderDecorator(); } } class Highlander extends TrafficTool { @Override public void run() { System.out.println("汉兰达...run..."); } } class HighlanderDecorator extends Decorator { @Override public void decorate() { System.out.println("汉兰达装饰品..."); } }
一、简单工厂模式
其他语言的实现:
''' 抽象运算类,以及具体运算类:加、减、乘、除 ''' 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("\n") 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