问题描述
抽象工厂和工厂方法模式都是创造性设计模式,可以解决不同情况下的对象创建问题。根据GOF 工厂方法 pattern
我的理解:
动机客户端是在Base Factory中获取一个方法,该方法取决于具体类现在不知道的对象(在这种情况下,在向客户端提供软件时,它将会或者客户自己编写具体的实现,最有可能在框架的情况下)。未知(或可能更改)产品提供抽象类型:IP产品,并设定合同,以后产品的任何实施必须实现此接口。
IProduct接口
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();
//一些更多的代码
}
}
一些具体的产品
package com.companyx;
class AppAProductFeatureX实现IProduct {
@Override
public void serve(){
// some code
}
}
具体产品的工厂
package com.companyx;
public class AppAFeatureXProductFactory extends Factory {
@Override
public IProduct createProduct(){
返回新的AppAProductFeatureX();
}
}
客户端代码 p>
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;
//可以更好地命名,但是这个时候可以放这个名字
public class ProductAVersion1实现IProductA {
@Override
public void performAJob(){
//一些代码
}
}
strong>,(它也可以是抽象类)
package com.companyb;
public interface IFactory {
public IProductA createProduct();
}
Factory o创建ProductA的具体实现
package com.companyb;
public class FactoryA实现IFactory {
@Override
public IProductA createProduct(){
return new ProductAVersion1(); //具体类的产品隐藏
}
}
客户端代码
package com.clientcompany.productprovider;
import com.companyb.IFactory;
import com.companyb.IProductA;
public class SomeClientClass {
private IFactory factory;
私人IProductA产品;
public void doSomeJobWithProductA(){
// some code
product.performAJob();
// someCode();
}
public void setFactory(IFactory factory){
this.factory = factory;
this.product = factory.createProduct();
}
}
包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
,框架
,工厂方法
,抽象工厂
和产品系列
等。
,库vs框架
与工厂,抽象工厂或任何模式完全没有任何关系。图书馆与框架辩论不是从模式发挥的实现角度出发。例如,JUnit是一个带有丰富的断言库的框架。那么junit是否比其他内部实现更喜欢一种模式? Java本身是一个附带JCL库的框架。类似于java的DotNet甚至称之为框架,并且包含BCL库。所以在实现上下文中没有更多的框架与图书馆辩论。
所以这个问题归结为哪个模式应该使用?这不是关于差异,这是明确的,而是在哪种情况下使用哪一种。在这种情况下,客户端代码
是所有代码,可以调用
您正在输入的代码。一些代码是否由您或其他人在相同或不同的jar中由相同或不同的组织写入并不重要。从一个代码片段的角度来看,任何其他代码(即使在同一类的不同方法中)是客户端代码,如果该代码有潜力调用
您正在键入的代码。
在输入任何代码(无论框架或库状态)时,有时我们需要获取实例的一些对象。可能我们需要一个 BufferedReader
。如果在编译时,我们绝对确定对象的具体类, KISS
它,并与新
ing一起运行。
我们可能不知道实例的具体类。现在问问一下,客户端代码是否具有此信息?如果客户端代码知道实际的具体类,但是我不知道那么我们使用 FactoryMethod
模式。我正在输入的代码将在(说)其参数列表中询问工厂对象的实例。知道实际具体类的客户端代码将提供将创建的工厂对象。这种情况的例子见于 JDBC
,就像我们要处理一个sql语句一样。在编译时,我们不知道是否应该实例化一个 mysql.JDBC4PreparedStatement
或一个 microsoft.SQLServerStatement
。这取决于连接字符串,这取决于最终用户。所以我们得到一个 Connection
实例,并请求它到 createStatement()
。请参阅,我们将类型为 sql.Statement
的对象的构造委托给 sql.Connection
的子类。这里的 conn
实例是工厂对象。我们如何掌握工厂是无关紧要的,只是我们从客户端代码获得。
如果我们需要一个进程
对象,在编译时,我们不知道它是否将是一个 Win32Process
或 UnixProcess
,我们将其创建的责任委托给与工厂模式相关的 ProcessBuilder
,这是构建器模式
。对于 jdbc ConnectionManager
也是如此。
如果有许多不同的类不相关,但是由 family 我们可以使用 AbstractFactory
。例如,使用jdbc的点对点对象 DbProviderFactory
。我的代码需要 Connection
, Command
, DataReader
等等的实例它们与MySql或SqlServer的继承而不是由 family 相关。所以我们得到一个 DbProviderFactory
的子类的实例。可能是一个 MySqlProviderFactory
或一个 SqlProviderFactory
,这取决于运行时和客户端代码。一旦我们有了这个工厂,我们可以执行 CreateCommand()
, CreateConnection()
等。
希望这有助于您选择工厂模式和抽象工厂模式。
Both Abstract Factory and Factory method patterns are creational design patterns which solves the object creation issues in different scenarios.
As per GOF Factory Method pattern
My Understanding : Motive of the Client is to get a method present in the base Factory class get executed which is dependent upon an object whose concrete class is not known now (In such a case, either during providing the software to client, it will be defined, or it will be the client himself writing the concrete implementation, most likely in case of Framework). The not known (or likely to change) Product is provided an abstract type : IProduct, and setting a contract that in future any implementation for Product must implement this interface.
IProduct interface
package com.companyx;
public interface IProduct {
public void serve();
}
Factory class with 'a method' which needs to be executed
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
}
}
Some concrete Product
package com.companyx;
class AppAProductFeatureX implements IProduct{
@Override
public void serve() {
//some code
}
}
Factory of the concrete Product
package com.companyx;
public class AppAFeatureXProductFactory extends Factory{
@Override
public IProduct createProduct() {
return new AppAProductFeatureX();
}
}
Client code
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();
}
}
As per GOF Abstract Factory pattern
My UnderstandingThe client is interested in the products, here this pattern helps in providing the product by hiding the concrete product classes behind factory classes.
Product type wanted by the client
package com.companyb;
public interface IProductA {
public void performAJob();
}
Implementation of the product
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
}
}
Factory interface, (It can be also an abstract class)
package com.companyb;
public interface IFactory {
public IProductA createProduct();
}
Concrete implementation of Factory o create ProductA
package com.companyb;
public class FactoryA implements IFactory{
@Override
public IProductA createProduct() {
return new ProductAVersion1(); // concrete class of product is hidden
}
}
Client Code
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 : Is the family of related product necessary in Abstract Factory patter , won't this pattern still be relevant if only one kind of product (like above) is there with various sub types but not various related types?
Q2 Is my understanding above correct ?
Q3 Above brings another doubt in my mind : Is Factory method more suitable for frameworks (where client can give the implementation of products) and just like template method pattern, factory invokes the createProduct()
concrete implementation form the user provided Concrete Factory implementation ? Also similarly is Abstract factory more fits for Library development, where concrete product classes (likely to vary) are hidden behind more stable Factory classes ?
I am having real difficulty in getting into your shoes. But I am quite interested in this subject so I will give a try. Involved here are concepts like library
, framework
, factory method
, abstract factory
and product family
etc.
First, the library vs framework
has really nothing to do with factory, abstract factory or any pattern for that matter. Library vs framework debate is not from implementational perspective where the patterns play. For example JUnit is a framework which comes with a rich assertion library. So should junit prefer one pattern over other for its internal implementation? Java itself is a framework which comes with a JCL library. Dot Net which is similar to java even calls itself a framework, and contains BCL library. So no more framework vs library debate in implementational context.
So the question boils down to which pattern should you use? It is not about the difference, which is clear, but about which one to use in which scenario. In this context, the Client Code
is all code which may call
the one which you are typing right now. It does not matter whether some code is written by you or someone else, in same or different jar, from same or different organization. From perspective of one code fragment, any other code (even in different method of the same class) is client code if that code has a potential to call
the code which you are typing right now.
While typing any code (irrespective of framework or library status) sometimes we need to obtain instances of some object. May be we need a BufferedReader
. If at compile time we are absolute sure about the concrete class of the object, KISS
it and go with new
ing.
We may not know the concrete class of an instance. Now question aries whether the client code has this information? If the client code knows about the actual concrete class, but I do not know then we use the FactoryMethod
pattern. The code I am typing will ask for an instance of a factory object in (say) its argument list. The client code knowing the actual concrete class, will supply a factory object which will do the creation. Example of this case is seen in JDBC
like we want to process an sql statement. At compile time we do not know whether we should instantiate a mysql.JDBC4PreparedStatement
or a microsoft.SQLServerStatement
. It depends on connection string and that depends on end user. So we get hold of a Connection
instance and ask it to createStatement()
. See, we are delegating the construction of an object of type sql.Statement
to a subclass of sql.Connection
. Here the conn
instance is the factory object. How we get hold of the factory is immaterial, just that we got it from client code.
If we need an instance of a Process
object and at compile time we do not know whether it will be a Win32Process
or a UnixProcess
, we delegate the responsibility of its creation to ProcessBuilder
which is builder pattern
related to factory pattern. Same goes for jdbc ConnectionManager
.
In case when there are many different classes not related by inheritance but by family we may use AbstractFactory
. For example take jdbc's dot net counterpart DbProviderFactory
. My code needs instances of Connection
, Command
, DataReader
etc which are not related by inheritance but by family of MySql or SqlServer. So we get hold of an instance of a subclass of DbProviderFactory
. May be it is a MySqlProviderFactory
or a SqlProviderFactory
that depends on runtime and client code. Once we have that factory, we can do CreateCommand()
, CreateConnection()
etc.
Hope this helps you choose between factory pattern and abstract factory pattern.
这篇关于工厂方法是否更适合图书馆的框架和抽象方面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!