Is Factory method more suitable for frameworks and Abstract facory for Library?

放肆的年华 提交于 2019-12-08 05:47:20

问题


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 newing.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!