What are the differences between Abstract Factory and Factory design patterns?

后端 未结 17 1186
醉话见心
醉话见心 2020-11-22 01:57

I know there are many posts out there about the differences between these two patterns, but there are a few things that I cannot find.

From what I have been reading,

17条回答
  •  闹比i
    闹比i (楼主)
    2020-11-22 02:48

    The main difference between Abstract Factory and Factory Method is that Abstract Factory is implemented by Composition; but Factory Method is implemented by Inheritance.

    Yes, you read that correctly: the main difference between these two patterns is the old composition vs inheritance debate.

    UML diagrams can be found in the (GoF) book. I want to provide code examples, because I think combining the examples from the top two answers in this thread will give a better demonstration than either answer alone. Additionally, I have used terminology from the book in class and method names.

    Abstract Factory

    1. The most important point to grasp here is that the abstract factory is injected into the client. This is why we say that Abstract Factory is implemented by Composition. Often, a dependency injection framework would perform that task; but a framework is not required for DI.
    2. The second critical point is that the concrete factories here are not Factory Method implementations! Example code for Factory Method is shown further below.
    3. And finally, the third point to note is the relationship between the products: in this case the outbound and reply queues. One concrete factory produces Azure queues, the other MSMQ. The GoF refers to this product relationship as a "family" and it's important to be aware that family in this case does not mean class hierarchy.
    public class Client {
        private final AbstractFactory_MessageQueue factory;
    
        public Client(AbstractFactory_MessageQueue factory) {
            // The factory creates message queues either for Azure or MSMQ.
            // The client does not know which technology is used.
            this.factory = factory;
        }
    
        public void sendMessage() {
            //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
            OutboundQueue out = factory.createProductA();
            out.sendMessage("Hello Abstract Factory!");
        }
    
        public String receiveMessage() {
            //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
            ReplyQueue in = factory.createProductB();
            return in.receiveMessage();
        }
    }
    
    public interface AbstractFactory_MessageQueue {
        OutboundQueue createProductA();
        ReplyQueue createProductB();
    }
    
    public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
        @Override
        public OutboundQueue createProductA() {
            return new AzureMessageQueue();
        }
    
        @Override
        public ReplyQueue createProductB() {
            return new AzureResponseMessageQueue();
        }
    }
    
    public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
        @Override
        public OutboundQueue createProductA() {
            return new MsmqMessageQueue();
        }
    
        @Override
        public ReplyQueue createProductB() {
            return new MsmqResponseMessageQueue();
        }
    }
    

    Factory Method

    1. The most important point to grasp here is that the ConcreteCreator is the client. In other words, the client is a subclass whose parent defines the factoryMethod(). This is why we say that Factory Method is implemented by Inheritance.
    2. The second critical point is to remember that the Factory Method Pattern is nothing more than a specialization of the Template Method Pattern. The two patterns share an identical structure. They only differ in purpose. Factory Method is creational (it builds something) whereas Template Method is behavioral (it computes something).
    3. And finally, the third point to note is that the Creator (parent) class invokes its own factoryMethod(). If we remove anOperation() from the parent class, leaving only a single method behind, it is no longer the Factory Method pattern. In other words, Factory Method cannot be implemented with less than two methods in the parent class; and one must invoke the other.
    public abstract class Creator {
        public void anOperation() {
            Product p = factoryMethod();
            p.whatever();
        }
    
        protected abstract Product factoryMethod();
    }
    
    public class ConcreteCreator extends Creator {
        @Override
        protected Product factoryMethod() {
            return new ConcreteProduct();
        }
    }
    

    Misc. & Sundry Factory Patterns

    Be aware that although the GoF define two different Factory patterns, these are not the only Factory patterns in existence. They are not even necessarily the most commonly used Factory patterns. A famous third example is Josh Bloch's Static Factory Pattern from Effective Java. The Head First Design Patterns book includes yet another pattern they call Simple Factory.

    Don't fall into the trap of assuming every Factory pattern must match one from the GoF.

提交回复
热议问题