要一直走下去

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

 

   举个例子: 有个汽车生产工厂,最开始规模比较小,轿车和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

posted on 2019-10-09 17:06  要一直走下去  阅读(177)  评论(0编辑  收藏  举报