Factory方法更适合图书馆的框架和抽象工具吗?

Abstract Factory和Factory方法模式都是创建设计模式,它解决了不同场景下的对象创建问题。

根据GOF 工厂方法模式

定义用于创建对象的接口,但让子类决定实例化哪个类。 Factory方法允许类将实例化延迟到子类。

我的理解: 客户端的动机是获得一个存在于基础工厂类中的方法得到执行,这取决于现在不知道具体类的对象(在这种情况下,无论是在向客户提供软件期间,它都将是定义,或者客户自己编写具体实现,最有可能是框架)。 未知(或可能更改)的产品提供了一种抽象类型:IProduct,并设置一个合同,以后在产品的任何实现中都必须实现此接口。

IProduct接口

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

带有’a method’的工厂类需要执行

 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 抽象工厂模式

提供用于创建相关或从属对象族的接口,而无需指定其具体类。

我的理解 客户对产品感兴趣,这种模式通过隐藏工厂类后面的具体产品类来帮助提供产品。

客户需要的产品类型

 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的具体实现o创建ProductA

package com.companyb;

 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 Above在我的脑海中带来了另一个疑问:Factory方法是否更适合框架(客户端可以提供产品的实现),就像模板方法模式一样,工厂调用createProduct()具体实现从用户提供的Concrete Factory实现? 同样,抽象工厂更适合图书馆开发,其中具体的产品类(可能会有所不同)隐藏在更稳定的工厂类之后?

我很难穿上你的鞋子。 但我对这个问题很感兴趣,所以我会试一试。 这里涉及的概念包括libraryframeworkfactory methodabstract factoryproduct family等。

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

所以问题归结为你应该使用哪种模式? 它不是关于差异,这是明确的,而是关于在哪种场景中使用哪一个。 在此上下文中, Client Code是可以call您正在键入的Client Code的所有代码。 一些代码是由您或其他人在相同或不同的jar中从相同或不同的组织编写的并不重要。 从一个代码片段的角度来看, 任何其他代码(即使在同一个类的不同方法中)也是客户端代码,如果该代码有可能call您正在键入的代码。

在键入任何代码(无论框架或库状态)时,有时我们需要获取某些对象的实例。 可能我们需要一个BufferedReader 。 如果在编译时我们绝对确定对象的具体类,请将其与KISS一起使用并与new一起使用。

我们可能不知道实例的具体类。 现在质疑客户端代码是否有此信息? 如果客户端代码知道实际的具体类,但我不知道,那么我们使用FactoryMethod模式。 我输入的代码将在(例如)其参数列表中请求工厂对象的实例。 知道实际具体类的客户端代码将提供将进行创建的工厂对象。 在JDBC可以看到这种情况的示例,就像我们要处理sql语句一样。 在编译时,我们不知道是否应该实例化mysql.JDBC4PreparedStatementmicrosoft.SQLServerStatement 。 它取决于连接字符串,这取决于最终用户。 所以我们得到一个Connection实例并要求它创建createStatement() 。 请参阅,我们将sql.Statement类型的对象的构造sql.Statementsql.Statement的子类。 这里的conn实例是工厂对象。 我们如何掌握工厂是无关紧要的,只是我们从客户代码中获得它。

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

如果有许多不同的类通过inheritance而不是由家族相关,我们可以使用AbstractFactory 。 例如,使用jdbc的dot net对应的DbProviderFactory 。 我的代码需要ConnectionCommandDataReader等实例,这些实例与inheritance无关,而是与MySql或SqlServer 系列有关。 所以我们得到了一个DbProviderFactory子类的实例。 可能是依赖于运行时和客户端代码MySqlProviderFactorySqlProviderFactory 。 一旦我们有了这个工厂,我们就可以做CreateCommand()CreateConnection()等。

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

在我的理解中:

A1 :产品系列不需要必然相关,如示例图所示 ,只需要具有产品类型知识的客户。 这种关系大多是自然的,因为你可能不希望同一个客户端创建2个不相关的对象,例如,如果你有一个创建Pizza和Cars的“AbstractPizzaFactory”,它看起来很奇怪,不是吗?

A2 :从技术上讲,您可以在Factory模式中提供默认的工厂方法,这样您仍然可以创建(默认)新对象,而无需始终对其进行子类化。

A3 :我同意你的观点,尽管创建一个图书馆或一个框架绝不是黑白分明的。

抽象工厂可以看作是工厂方法的集合。

为了更好地理解现实生活中的例子可以帮助:
工厂方法 – 橡皮泥/模具
抽象工厂 – 卡片厂