大牧絮叨设计模式:抽象工厂模式

1、 抽象工厂模式概述

抽象工厂模式(Abstract Factory)[GOF95]是一种对象的创建模式,是在工厂方法模式上的又一次改进,主要应用于多等级产品结构的项目架构中,将产品对象的创建过程产品对象的使用过程解耦合,使用抽象工厂模式的架构中业务模型从工厂对象中获取到产品对象,只需要关注产品对象的使用即可,而可能添加了较为复杂业务逻辑的创建过程封装在工厂内部,让系统中各个模块的责任更加明确。

1.1、 核心组件

抽象工厂模式中的核心组件,主要是对多等级类型架构的一种解决方案,核心包含了高度抽象的工厂接口,产品接口以及具体的实现过程,其架构如图所示:

image.png
  • 抽象工厂角色【Abstract Factory】:上图中的Factory,抽象工程概念方法模式的核心,与应用系统的商业逻辑无关,主要是工厂方法标准化的定义和构建。
  • 具体工厂角色【Concrete Factory】:上图中的MobileFactory以及ComputerFactory,该角色包含具体产品对象的创建业务逻辑,在使用时可以直接调用创建对应的产品对象。
  • 抽象产品角色【Abstract Product】:上图中的Xiaomi或者Dell,抽象产品体系可以是1到n套相同体系的产品结构,抽象产品体系的公共数据抽象就是抽象产品角色。
  • 具体产品角色【Concrete Product】:具体业务逻辑的实现类型,由具体工厂角色负责创建的实例对象,包含了具体业务处理逻辑的实例。

1.2、 优点缺点

抽象工厂模式最早是在操作系统构建过程中落地的一个设计概念,不同的操作系统在处理窗口以及窗口中的按钮、文字时涉及到类似的构建过程,在该架构模式下工厂架构和对应的产品架构之间会产生对应的耦合关系,在业务逻辑中必须使用具体的某个产品系列,可以支持相似架构的其他产品系列,如果是类似的模式可以通过抽象工厂设计模式进行架构,作为创建模式中一种非常经典的设计模式,是很多设计模式的最原始的实现架构,在该模式的基础上可以变通实现多种设计实现。

优点:

  • 产品的创建、组合和表现形式解耦合,在系统中形成两套不同的体系,将构建与业务分离。
  • 多个产品系统可以无缝切换,并且不会影响整体系统的稳定性。
  • 客户端依赖系统的抽象层,所有产品体系结构相似,客户端不依赖产品实现。
  • 系统整体扩展性提高,满足OCP原则。

缺点:

  • 多个产品体系必须相似【固定架构模式,设计约束性较高】
  • 业务无关代码的冗余较多。

2、 Java实现

2.1、 工厂及产品结构的定义

package com.damu.inter;

/**
 * <p>项目文档: 抽象工厂声明</p>
 *
 * @author 大牧
 * @version V1.0
 */
public interface IFactory<T> {
    /**
     * 产品创建方法
     * @param objects 参数列表
     * @return 创建好的产品对象
     */
    T product(Object ... objects);
}
---------------------------------------------
package com.damu.inter;

/**
 * <p>项目文档: 抽象产品声明</p>
 *
 * @author 大牧
 * @version V1.0
 */
public interface IProduct {
    String getInformation();
}

2.2、 具体工厂类的实现

游戏本工厂类

package com.damu.factory;

import com.damu.inter.IFactory;
import com.damu.inter.IProduct;
import com.damu.product.XiaomiGameComputer;

/**
 * <p>项目文档: 游戏计算机制造工厂类</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class GameComputerFactory implements IFactory<IProduct> {

    @Override
    public IProduct product(Object... objects) {
        return null;
    }

    /**
     * 小米游戏本制造方法
     * @return 小米游戏本
     */
    public IProduct productXiaomi() {
        return new XiaomiGameComputer();
    }

    /**
     * Dell游戏本制造方法
     * @return Dell游戏本
     */
    public IProduct productDell() {
        return null;
    }
}

商务本工厂处理类

package com.damu.factory;

import com.damu.inter.IFactory;
import com.damu.inter.IProduct;
import com.damu.product.XiaomiBusinessComputer;

/**
 * <p>项目文档: 商务计算机制造工厂类</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class BusinessComputerFactory implements IFactory<IProduct> {

    @Override
    public IProduct product(Object... objects) {
        return null;
    }

    /**
     * 小米商务本制造方法
     * @return 小米商务本对象
     */
    public IProduct productXiaomi() {
        return new XiaomiBusinessComputer();
    }

    /**
     * 戴尔商务本制造方法
     * @return 戴尔商务本
     */
    public IProduct productDell() {
        return null;
    }
}

学生本工厂处理类

package com.damu.factory;

import com.damu.inter.IFactory;
import com.damu.inter.IProduct;
import com.damu.product.XiaomiEduComputer;

/**
 * <p>项目文档: 学生计算机制造工厂类</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class EduComputerFactory implements IFactory<IProduct> {
    @Override
    public IProduct product(Object... objects) {
        return null;
    }

    /**
     * 小米学生本制造方法
     * @return 小米学生本
     */
    public IProduct productXiaomi() {
        return new XiaomiEduComputer();
    }

    /**
     * Dell学生本制造方法
     * @return Dell学生本
     */
    public IProduct productDell() {
        return null;
    }
}

具体产品体系的父类构建

package com.damu.inter.extend;

import com.damu.inter.IProduct;

/**
 * <p>项目文档: Dell产品父类</p>
 *
 * @author 大牧
 * @version V1.0
 */
public interface IDell extends IProduct {
}
----------------------------------------------
package com.damu.inter.extend;

import com.damu.inter.IProduct;

/**
 * <p>项目文档: 小米产品父类</p>
 *
 * @author 大牧
 * @version V1.0
 */
public interface IXiaomi extends IProduct {
}

具体产品构建

package com.damu.product;

import com.damu.inter.extend.IXiaomi;

/**
 * <p>项目文档: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class XiaomiGameComputer implements IXiaomi {
    @Override
    public String getInformation() {
        return "小米游戏本,最佳性价比";
    }
}
--------------------------------------------
package com.damu.product;

import com.damu.inter.extend.IXiaomi;

/**
 * <p>项目文档: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class XiaomiBusinessComputer implements IXiaomi {
    @Override
    public String getInformation() {
        return "小米商务本,最佳选择";
    }
}
--------------------------------------------
package com.damu.product;

import com.damu.inter.extend.IDell;

/**
 * <p>项目文档: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class DellGameComputer implements IDell {
    @Override
    public String getInformation() {
        return "Dell游戏,Alienware,王者归来";
    }
}

package com.damu.product;

import com.damu.inter.extend.IXiaomi;

/**
 * <p>项目文档: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class XiaomiEduComputer implements IXiaomi {
    @Override
    public String getInformation() {
        return "小米学生本,学生党的福利";
    }
}
--------------------------------------------
package com.damu.product;

import com.damu.inter.extend.IDell;

/**
 * <p>项目文档: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class DellGameComputer implements IDell {
    @Override
    public String getInformation() {
        return "Dell游戏,Alienware,王者归来";
    }
}
--------------------------------------------more.....

测试代码,使用工厂构建产品过程

package com.damu.main;

import com.damu.factory.GameComputerFactory;
import com.damu.inter.IFactory;
import com.damu.inter.IProduct;
import com.damu.product.XiaomiGameComputer;

/**
 * <p>项目文档: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class Main {

    public static void main(String[] args) {
        // 创建工厂对象
        GameComputerFactory factory = new GameComputerFactory();

        // 创建小米游戏本
        IProduct productXiaomi = factory.productXiaomi();
        System.out.println(productXiaomi.getInformation());
        // 创建Dell游戏本
        IProduct productDell = factory.productDell();
        System.out.println(productDell.getInformation());

        // more....
    }
}

3、 Python实现

"""
抽象工厂模式
"""
import abc


# ------------------------------------------ 接口层
class IFactory(metaclass=abc.ABCMeta):
    """工厂接口"""

    @abc.abstractmethod
    def product(self):
        raise NotImplementedError("该方法必须在子类中实现")


class IProduct(metaclass=abc.ABCMeta):
    """产品抽象接口"""

    def get_information(self):
        raise NotImplementedError("该方法必须在产品子类中实现")


# ------------------------------------------ 抽象层
class DellComputer(IProduct):
    """Dell电脑产品抽象类"""
    pass


class XiaomiComputer(IProduct):
    """小米产品抽象类"""
    pass


# ------------------------------------------ 实现层
class XiaomiGameComputer(IProduct):
    """产品具体:小米游戏本"""

    def get_information(self):
        print("小米游戏,品质佳轩")


class DellGameComputer(IProduct):
    """产品具体:Dell游戏本"""

    def get_information(self):
        print("Dell游戏,Alienware出击")


class GameComputerFactory(IFactory):
    """游戏本工厂处理类"""

    def product(self):
        print("小米游戏本:product_xiaomi(); Dell游戏本:product_dell()")

    def product_xiaomi(self):
        return XiaomiGameComputer()

    def product_dell(self):
        return DellGameComputer()

# 其他 具体产品 对应 具体工厂 产品体系和工厂体系保持一致即可


if __name__ == "__main__":
    # 创建工厂对象
    game_factory = GameComputerFactory()

    # 创建具体产品
    xiao_mi = game_factory.product_xiaomi()

    dell = game_factory.product_dell()

    # 打印
    xiao_mi.get_information()
    dell.get_information()

4、 Go实现

package main

import "fmt"

/*************** 接口层 ****************/
type IProduct interface {
    // 抽象产品接口
    GetInformation() string
}

type IFactory interface {
    // 抽象工厂接口
    product() IProduct
}

/*************** 抽象产品层 ****************/
type XiaomiComputer interface {
    IProduct
}

type DellComputer interface {
    IProduct
}

/*************** 具体产品层 ****************/
type XiaomiGameComputer struct {
    XiaomiComputer
}

func (computer XiaomiGameComputer) GetInformation() string {
    return "小米游戏,品质佳选"
}

type DellGameComputer struct {
    DellComputer
}

func (computer DellGameComputer) GetInformation() string {
    return "Alienware,笔记本中的王者"
}

/*************** 具体工厂层 ****************/
type GameComputerFactory struct {}

func (gameComputerFactory GameComputerFactory) product_xiaomi() IProduct {
    return new(XiaomiGameComputer)
}

func (gameComputerFactory GameComputerFactory) product_dell() IProduct {
    return new(DellGameComputer)
}

/*************** 具体测试 ****************/
func main()  {
    // 创建工厂对象
    gameComputerFactory := new(GameComputerFactory)

    // 创建具体产品
    dellComputer := gameComputerFactory.product_dell()
    fmt.Println(dellComputer.GetInformation())

    xiaomiComputer := gameComputerFactory.product_xiaomi()
    fmt.Println(xiaomiComputer.GetInformation())
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容

  • 设计原则: 要依赖抽象,不要依赖具体类 目录 本文的结构如下: 什么是抽象工厂模式 为什么要用该模式 模式的结构 ...
    w1992wishes阅读 1,107评论 0 6
  • 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一...
    justCode_阅读 1,193评论 1 6
  • 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。通常我们所说的工厂模式是指工厂方法模...
    zfylin阅读 1,312评论 0 7
  • 简单工厂模式虽然简单,但存在一个很严重的问题。当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建...
    justCode_阅读 1,181评论 1 9
  • 1。后台优化,启用页面缓存 2。dns域名解析加速 3。使用cdn加速 4。采用多台服务器提高并行加载量,例如负载...
    醉酒的姑娘阅读 321评论 0 0