工厂方法更适合框架,抽象工厂更适合库吗?

2024-03-07

抽象工厂和工厂方法模式都是创建型设计模式,解决了不同场景下的对象创建问题。

根据 GOF工厂方法 pattern

定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法让类将实例化推迟到子类。

我的理解 :动机Client是获取执行的工厂基类中存在的方法,该方法依赖于现在未知其具体类的对象(在这种情况下,要么在向客户端提供软件期间,要么将其定义,要么将是客户自己编写具体的实现,最有可能在框架的情况下)。为未知(或可能更改)的产品提供一个抽象类型:IProduct,并设置一个约定,将来任何产品的实现都必须实现此接口。

I产品界面

package com.companyx;
public interface IProduct {
    public void serve();
}

带有需要执行的“方法”的工厂类

package com.companyx;
public abstract class Factory {
    public abstract IProduct createProduct();
    private void performCriticalJob(){
        IProduct product = createProduct();
        product.serve();
    }
    public void executeJob(){
        //some code
        performCriticalJob();
        //some more code
    }
}

一些具体产品

package com.companyx;
class AppAProductFeatureX implements IProduct{
    @Override
    public void serve() {
        //some code
    }
}

混凝土制品厂

package com.companyx;
public class AppAFeatureXProductFactory extends Factory{
    @Override
    public IProduct createProduct() {
        return new AppAProductFeatureX();
    }
}

客户端代码

package com.clientcompany;
import com.companyx.AppAFeatureXProductFactory;
import com.companyx.Factory;
public class Client {
    public static void main(String[] args) {
        Factory fact = new AppAFeatureXProductFactory();
        fact.executeJob();
    }
}

根据 GOF抽象工厂 pattern

提供一个接口,用于创建相关或依赖对象系列,而无需指定它们的具体类。

我的理解 The client对产品感兴趣,这里这种模式有助于通过将具体产品类隐藏在工厂类后面来提供产品。

客户想要的产品类型

package com.companyb;
public interface IProductA {
    public void performAJob();
}

产品实施

package com.companyb;
//can be named better, but lets go with this name for this time
public class ProductAVersion1 implements IProductA{
    @Override
    public void performAJob() {
        // some code
    }
}

工厂界面,(也可以是抽象类)

package com.companyb;
public interface IFactory {
    public IProductA createProduct();
}

Factory创建ProductS的具体实现

包 com.company;

public class FactoryA implements IFactory{
    @Override
    public IProductA createProduct() {
        return new ProductAVersion1(); // concrete class of product is hidden
    }
}

客户端代码

package com.clientcompany.productprovider;
import com.companyb.IFactory;
import com.companyb.IProductA;
public class SomeClientClass {
    private IFactory factory;
    private IProductA product;

    public void doSomeJobWithProductA() {
        // some code
        product.performAJob();
        //someCode();
    }
    public void setFactory(IFactory factory) {
        this.factory = factory;
        this.product = factory.createProduct();
    }
}

package com.clientcompany.productprovider;
import com.companyb.FactoryA;
public class SomeOtherClientCode {
    public static void main(String[] args) {
        SomeClientClass someClientClass = new SomeClientClass();
        someClientClass.setFactory(new FactoryA());
        someClientClass.doSomeJobWithProductA();
    }
}

Q1:抽象工厂模式中相关产品系列是否是必要的,如果只有一种产品(如上)存在各种子类型但没有各种相关类型,那么这种模式是否仍然相关?

Q2我上面的理解正确吗?

Q3以上给我带来了另一个疑问:工厂方法是否更适合框架(客户端可以给出产品的实现),就像模板方法模式一样,工厂调用createProduct()具体实现形式是用户提供的Concrete Factory实现? 同样,抽象工厂是否更适合库开发,其中具体的产品类(可能会有所不同)隐藏在更稳定的工厂类后面?


我真的很难进入你的处境。但我对这个科目很感兴趣,所以我会尝试一下。这里涉及到的概念有library, framework, factory method, abstract factory and product family etc.

首先,library vs framework实际上与工厂、抽象工厂或任何与此相关的模式无关。库与框架的争论不是从模式发挥作用的实现角度来看的。例如,JUnit 是一个带有丰富断言库的框架。那么,junit 在其内部实现中是否应该更喜欢一种模式而不是其他模式呢? Java本身是一个框架,带有JCL库。 Dot Net类似于java,甚至称自己为框架,并且包含BCL库。因此,在实现环境中不再有框架与库的争论。

所以问题归结为您应该使用哪种模式?这不是关于差异的问题,这一点很明显,而是关于在哪种情况下使用哪一种。在此背景下,Client Code是所有可能的代码call您现在正在输入的那个。某些代码是由您还是其他人在相同或不同的 jar 中、来自相同或不同的组织编写并不重要。从一个代码片段来看,any其他代码(即使在同一类的不同方法中)是客户代码如果该代码有潜力call您现在正在输入的代码。

在键入任何代码时(无论框架或库状态如何),有时我们需要获取某些对象的实例。也许我们需要一个BufferedReader。如果在编译时我们绝对确定对象的具体类,KISS它并伴随newing.

我们可能不知道实例的具体类。现在质疑白羊座是否客户代码有这个信息吗?如果客户端代码知道实际的具体类,但我不知道,那么我们使用FactoryMethod图案。我正在输入的代码将在(比如说)其参数列表中请求工厂对象的实例。知道实际具体类的客户端代码将提供一个工厂对象来进行创建。这种情况的例子见于JDBC就像我们要处理一条sql语句一样。在编译时我们不知道是否应该实例化一个mysql.JDBC4PreparedStatement or a microsoft.SQLServerStatement。它取决于连接字符串,并且取决于最终用户。所以我们得到一个Connection实例并要求它createStatement()。看,我们正在委托类型对象的构造sql.Statement的一个子类sql.Connection。这里的conn实例是工厂对象。我们如何获得工厂并不重要,重要的是我们是从哪里获得的客户代码.

如果我们需要一个实例Process对象并且在编译时我们不知道它是否会是一个Win32Process or a UnixProcess,我们将其创建的责任委托给ProcessBuilder这是builder pattern与工厂模式相关。同样适用于jdbc ConnectionManager.

如果有许多不同的类不是通过继承相关而是通过family我们可以使用AbstractFactory。例如,采用 jdbc 的 dot net 对应项DbProviderFactory。我的代码需要实例Connection, Command, DataReader等不是通过继承相关而是通过familyMySql 或 SqlServer 的。所以我们得到了一个子类的实例DbProviderFactory。也许它是一个MySqlProviderFactory or a SqlProviderFactory这取决于运行时和客户代码。一旦我们有了那个工厂,我们就可以做CreateCommand(), CreateConnection() etc.

希望这可以帮助您在工厂模式和抽象工厂模式之间进行选择。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

工厂方法更适合框架,抽象工厂更适合库吗? 的相关文章

  • 在 Java 中使用 Batik 检查和删除 SVG 中的属性

    这个问题基本上说明了一切 如何检查 SVG 是否具有 viewBox 属性 我正在使用蜡染库 我需要这个 因为我需要 至少 通知用户有一个 viewBox 属性 我可以删除它吗 使用 org w3c dom 类 您可以按照以下方式做一些事情
  • 使类只能从特定类实例化

    假设我有 3 节课class1 class2 and class3 我怎样才能拥有它class1只能通过实例化class2 class1 object new class1 但不是 class3 或任何其他类 我认为它应该与修饰符一起使用
  • 重写 getPreferredSize() 会破坏 LSP

    我总是在这个压倒一切的网站上看到建议getPreferredSize 而不是使用setPreferredSize 例如 如前面的线程所示 对于固定大小的组件 使用重写 getPreferredSize 而不是使用 setPreferredS
  • 记录共享和映射的诊断上下文

    据我所知 其他人做了什么来解决 Commons Logging 项目 针对 NET 和 Java 不支持映射或嵌套诊断上下文这一事实 执行摘要 我们选择直接使用实现者日志框架 在我们的例子中为 log4j 长答案 您是否需要一个抽象日志框架
  • 如何在 MSSQL 中获取 CURRENT_DATE?

    我正在使用 jpa 3 o 和 Hibernate 我有一个命名查询 SELECT COUNT wt id FROM WPSTransaction wt WHERE wt createdDate gt CURRENT DATE WPSTra
  • 在java中将字符串日期转换为美国格式

    我有下面的代码 其中日期为字符串类型 我必须将其设置为美国格式 所以下面我已经展示了它 private static final SimpleDateFormat usOutputDate new SimpleDateFormat MM d
  • 无法从资源加载图片

    So I am trying to load a image file from a resource so that when I export my application into a jar file it could be use
  • 可访问数据的 Java 约定。 (公共访问器和 Getter/命名)

    通过 Java API 您会看到大量冲突的命名和实践 这让我感到非常困惑 例如 The String http grepcode com file repository grepcode com java root jdk openjdk
  • Javascript:我应该隐藏我的实现吗?

    作为一名 C 程序员 我有一个习惯 将可以而且应该私有的东西设为私有 当 JS 类型向我公开其所有私有部分时 我总是有一种奇怪的感觉 而且这种感觉并没有被 唤起 假设我有一个类型draw方法 内部调用drawBackground and d
  • R 中使用 `UseMethod()` 与 `inherits()` 来确定对象的类

    如果我需要根据 R 对象的类以不同的方式处理它们 我可以使用if and else在单个函数内 foo lt function x if inherits x list Foo the list else if inherits x num
  • JUNIT 测试 void 方法

    我有一个充满 void 方法的 java 类 我想进行一些单元测试以获得最大的代码覆盖率 例如我有这个方法 protected static void checkifValidElements int arg1 int arg2 metho
  • 嵌套字段的 Comparator.comparing(...)

    假设我有一个这样的域模型 class Lecture Course course getters class Course Teacher teacher int studentSize getters class Teacher int
  • C 与 C++ 中的 JNI 调用不同?

    所以我有以下使用 Java 本机接口的 C 代码 但是我想将其转换为 C 但不知道如何转换 include
  • BadPaddingException:无效的密文

    我需要一些帮助 因为这是我第一次编写加密代码 加密代码似乎工作正常 但解密会引发错误 我得到的错误是 de flexiprovider api exceptions BadPaddingException 无效的密文 in the 解密函数
  • 删除 JFX 中选项卡后面的灰色背景

    So is there any way to remove the gray area behind the tab s 我尝试过用 CSS 来做到这一点 但没有找到方法 要设置 tabpane 标题的背景颜色 请在 CSS 文件中写入 t
  • java中使用多线程调用同一类的不同方法

    我有一个类 如下所示 具有三种方法 public class MyRunnable implements Runnable Override public void run what code need to write here to c
  • 如何从 JavaFX 中的另一个控制器类访问 UI 元素?

    我有一个使用 NetBeans 8 编写的 JavaFX Java 8 应用程序 没有SceneBuilder 我的应用程序有一个主窗口 该窗口有自己的 FXML 文件 primary fxml 和自己的控制器类 FXMLPrimaryCo
  • 在实现使用原始类型的接口时如何避免警告?

    我正在实施流程工厂 http help eclipse org ganymede index jsp topic org eclipse platform doc isv reference api org eclipse debug co
  • 如何使用自定义 JDK 构建 Jenkins 项目?

    我有一个常规的 Jenkins 实例 运行一些多分支管道 该实例在 JDK 11 上运行 因为 Jenkins 并不真正支持更高版本 没关系 但不好的是 我的所有管道似乎也都受到 Java 11 的限制 Jenkins 仅使用它自己也使用的
  • mybatis:使用带有 XML 配置的映射器接口作为全局参数

    我喜欢使用 XML 表示法来指定全局参数 例如连接字符串 我也喜欢 Mapper 注释 当我尝试将两者结合起来时 我得到这个例外 https stackoverflow com questions 4263832 type interfac

随机推荐

  • ios - 多个导航控制器之间的导航

    我试图理解使用 和不使用 NavigationController 在 ViewController 之间导航的行为 并且在阅读文章和文档时我误解了一些事情 所以我决定问他们 主要问题是 如果故事板中有多个导航控制器并且想要从一个导航控制器
  • cython 做了哪些 numpy 优化?

    我有点惊讶地发现 fast ops c pyx cimport cython cimport numpy as np cython boundscheck False turn off bounds checking for entire
  • C++ 打印指针的值

    我有一个双指针数组 但每次我尝试打印其中一个值时 都会打印地址 如何打印实际值 cout 有人知道吗 如果它确实是一个 初始化的 双指针数组 即 double arr Initialize individual values 所有你需要的是
  • UIDatePicker设置最小和最大小时

    如何设置 UIDatePicker 的最小和最大小时 到底有可能吗 我知道如何设置最小和最大日期 datePicker setMinimumDate 今天 datePicker setMaximumDate nextMonthDay 我想要
  • 如何进行多对多 Django 查询来查找具有 2 个给定作者的书籍?

    我有一个查询 需要使用 ID 精确过滤 2 位作者 理论上 Book objects filter author id 1 author id 2 这是不可能的 我怎么解决这个问题 干杯 米奇 一开始并不直观 但答案就在我们面前 Book
  • knex.js 查询“承诺”何时执行/解析?

    对于正常的承诺 一旦当前代码停止 承诺就会尽快解决 考虑以下伪代码 const p SomePromiseDoingLoad calculatethings await sleepPromise during sleep the promi
  • VB:游戏之上的应用

    我想编写一个应用程序 在全屏游戏上绘制某个视觉对象 例如半透明三角形 该游戏具有 强置顶 属性 因为它涵盖了所有其他分类为 置顶 的应用程序 我需要我的应用程序是最上面的应用程序 并且始终处于焦点 而不影响后面游戏的顺利运行 如何才能有效地
  • 查找 Maven Google App Engine 项目的原型

    我正在使用 Eclipse 和 m2eclipse 插件为 Google App Engine 创建一个新的 Java 项目 创建新的 Maven 项目时 Eclipse 找不到原型 com google appengine archety
  • 由 javascript 更新的 asp.net mvc 禁用文本框不会发布新值

    我正在使用强类型模型来表达我的观点 我有一个禁用的文本框 我使用 javascript 更新其值 文本框是使用这个渲染的 这将呈现一个文本框 其中 NAME 和 ID 为 TotalAmount TotalAmount 也是我的模型上绑定到
  • cx_Freeze 后 Paramiko 无法正常工作?

    所以我编写了这段代码 我使用 Paramiko 通过 SSH 连接到计算机 脚本正常工作 但是当我使用 cx Freeze 将其转换为 exe 时 程序在 self ssh load system host keys 处停止工作 所以我从脚
  • 将表示列表的字符串转换为实际的列表对象[重复]

    这个问题在这里已经有答案了 我有一个代表列表的字符串 22 33 36 41 46 49 56 72 85 92 95 98 107 118 120 123 124 126 127 130 149 157 161 171 174 177 1
  • flutter中的webview是否缓存网页?

    我想缓存在 flutter webview 中显示的网页 以便提高性能 无需重新加载页面 可以用吗 我可以实施吗 flutter inappwebview 前 flutter inappbrowser 有参数cacheEnabled默认为
  • 如何从 Google Places API 获取地点描述

    我正在尝试使用 Google 地点 API 来获取某些地点的信息 我有一个 来自谷歌搜索的示例 这是我试图找到的 我认为 Places API 文本搜索的 类型 字段将包含它 但该文本似乎不同 并且不在提供的选项列表中 如果有人可以提供一些
  • .Net 中的 Oracle 连接池

    我们有一个使用 Oracle 数据库的系统 有人问我系统是否使用连接池 但我不确定 我们正在使用Oracle DataAccess Client OracleConnection 在阅读该主题时 我发现连接字符串中的连接池设置为 true
  • 在vagrant box上创建虚拟主机

    我正在尝试设置一个基于 Chef 提供的 vagrant 的开发环境 我使用 Apache 使用 Chef 创建了一个环境 并且可以通过端口转发从我的主机访问 Web 服务器 我想让我的流浪盒包含多个虚拟主机 并且通过共享文件夹 我将定义不
  • spring-boot oauth2 拆分授权服务器和资源服务器

    我试图在 spring boot 中将资源服务器与授权服务器分开 我有两个单独运行的不同应用程序 在授权服务器中 我可以从 oauth token 获取不记名令牌 但是当我尝试访问资源 在标头中发送令牌 时 我收到无效令牌错误 我的目的是使
  • AZURE Active Directory - 服务主体和企业应用程序之间有什么区别?

    我经常对 Azure AD 中的三个主题感到困惑 服务负责人 企业应用 应用程序注册 有什么不同 我可以轻松进入 应用程序注册 并注册一个 应用程序 而该 应用程序 甚至不需要存在 它所需要的只是一个 URL 也可以是完全随机的 然后 此应
  • 如何对命令行参数进行单元测试?

    我正在尝试向 Python 提供命令行参数unittest并面临一些问题 我在互联网上搜索并找到了一种提供参数的方法 unittest main argv myArg 问题是这对于单个命令行参数工作正常 但对于多个参数则失败 unittes
  • 为 Heroku 静态编译 pdftk。需要将PDF分割成单页文件

    所以我们使用 heroku 来托管我们的 Rails 应用程序 我们已经搬到雪松堆了 该堆栈没有安装 pdftk 库 我联系了支持人员 并被告知为 amd64 ubuntu 静态编译它并将其包含在我的应用程序中 事实证明这比我想象的要困难
  • 工厂方法更适合框架,抽象工厂更适合库吗?

    抽象工厂和工厂方法模式都是创建型设计模式 解决了不同场景下的对象创建问题 根据 GOF工厂方法 pattern 定义一个用于创建对象的接口 但让子类决定实例化哪个类 工厂方法让类将实例化推迟到子类 我的理解 动机Client是获取执行的工厂