问题
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
Define an interface for creating an object, but let the subclasses decide which class to instantiate. Factory method lets a class defer instantiation to subclass.
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
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
My Understanding The 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 ?
回答1:
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.
回答2:
In my understanding:
A1: The family of product does not need to be necessarily related, as shown on an example diagram, only a Client is needed that has knowledge of the type of products. The relation is mostly natural as you probably don't want the same Client to create 2 unrelated objects, e.g., it would look strange if you have an "AbstractPizzaFactory" that creates Pizza and Cars, no?
A2: Technically you can provide a default factory method in the Factory pattern, so that you can still create (defaults) new Objects without always subclassing it.
A3: I would agree with you on this point, although creating a Library or a Framework is never black and white.
回答3:
Abstract Factory can be seen as collection of the Factory Methods.
For better understanding examples from real life can help:
Factory Method - plasticine/mold
Abstract Factory - cards factory
来源:https://stackoverflow.com/questions/42516772/is-factory-method-more-suitable-for-frameworks-and-abstract-facory-for-library