序
本文主要是记录学习设计模式当中的工厂方法和抽象工厂时碰到的疑惑和对答案的探讨
刚接触时的工厂方法模式和抽象工厂模式
工厂方法模式
类图
代码
java">
//工厂public interface TVFactory {TV produce();
}public class TclTVFactory implements TVFactory{@Overridepublic TV produce() {System.out.println("TCL工厂生产了一台TCL电视");return new TclTV();}
}//产品public interface TV {void play();
}public class TclTV implements TV{@Overridepublic void play() {System.out.println("你好,我是TCL电视");}
}
java">public class Client {public static void main(String[] args) {TVFactory factory;TV tv;factory = new TclTVFactory();tv = factory.produce();tv.play();}
}
运行结果
TCL工厂生产了一台TCL电视
你好,我是TCL电视
根据上面的方法,当需要增加生产一个品牌的产品时,例如生产hisense电视,只需要再增加一个工厂类HisenseTVFactory实现TVFactory接口,和一个产品类HisenseTV实现TV接口即可,无需改动源代码,符合开闭原则。
抽象工厂模式
类图
代码
java">public interface Factory {TV produceTV();Fridge produceFridge();}public class TCLFactory implements Factory{@Overridepublic TV produceTV() {System.out.println("生产了TCL电视");return new TclTV();}@Overridepublic Fridge produceFridge() {System.out.println("生产了TCL冰箱");return new TclFridge();}
}public class HisenseFactory implements Factory{@Overridepublic TV produceTV() {System.out.println("生产了海信电视");return new HisenseTV();}@Overridepublic Fridge produceFridge() {System.out.println("生产了海信冰箱");return new HisenseFridge();}
}
java">public interface TV {void play();
}public class TclTV implements TV{@Overridepublic void play() {System.out.println("我是TCL电视");}
}public class HisenseTV implements TV{@Overridepublic void play() {System.out.println("我是海信电视");}
}public interface Fridge {void cooling();
}public class TclFridge implements Fridge{@Overridepublic void cooling() {System.out.println("我是TCL冰箱");}
}public class HisenseFridge implements Fridge{@Overridepublic void cooling() {System.out.println("我是海信冰箱");}
}
java">public class Client {public static void main(String[] args) {Factory factory;TV tv;Fridge fridge;factory = new HisenseFactory();tv = factory.produceTV();tv.play();fridge = factory.produceFridge();fridge.cooling();}
}
运行结果
生产了海信电视
我是海信电视
生产了海信冰箱
我是海信冰箱
由以上可知,抽象工厂模式增加产品族的时候是不需要修改原来的代码的符合开闭原则,但是增加产品等级结构,那就不适用了
学完工厂方法模式和抽象工厂模式后的问题
相信许多人和我一样,在学完上述两个模式后,再看到模式的分类,就会产生一个疑问
模式的分类就是工厂方法模式属于类模式,抽象工厂模式属于对象模式
看到这里我云里雾里的,什么是类模式什么是对象模式?好吧,以下是软设教材的概念
看到这里还是不懂,而且我发现用之前的工厂方法和抽象工厂方法的类图去套这条解释,我会发现,要么都是类模式要么都是对象模式,没有什么不同啊(都是增加一个抽象工厂/具体工厂和抽象产品/具体产品,client的调用也是一样的)
由此我开始了漫长的探索之路,直到我看到了这篇解释,突然豁然开朗,为避免歧义,我粘贴原文,有需要的自行复制翻译
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
- 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.
- The second critical point is that the concrete factories here are not Factory Method implementations! Example code for Factory Method is shown further below.
- 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.
java">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 {@Overridepublic OutboundQueue createProductA() {return new AzureMessageQueue();}@Overridepublic ReplyQueue createProductB() {return new AzureResponseMessageQueue();} }public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {@Overridepublic OutboundQueue createProductA() {return new MsmqMessageQueue();}@Overridepublic ReplyQueue createProductB() {return new MsmqResponseMessageQueue();} }
Factory Method
- The most important point to grasp here is that the is the client. In other words, the client is a subclass whose parent defines the . This is why we say that Factory Method is implemented by Inheritance.
ConcreteCreator
factoryMethod()
- 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).
- And finally, the third point to note is that the (parent) class invokes its own . If we remove 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.
Creator
factoryMethod()
anOperation()
java">public abstract class Creator {public void anOperation() {Product p = factoryMethod();p.whatever();}protected abstract Product factoryMethod(); }public class ConcreteCreator extends Creator {@Overrideprotected Product factoryMethod() {return new ConcreteProduct();} }
再配合软设教材的两个类图,这才发现两者的区别
工厂方法模式
抽象工厂模式
好了,就说到这里了,剩下的就靠大家自己体会领悟了,再见^_^
附录:
参考书籍
《软件设计师教程》
相关论坛
java">https://stackoverflow.com/questions/46041363/why-is-factory-method-a-class-pattern-while-an-abstract-factory-an-object-patte
https://stackoverflow.com/questions/5739611/what-are-the-differences-between-abstract-factory-and-factory-design-patterns#
https://blog.csdn.net/lovelion/article/details/9319481