?
?
跟着ZHONGHuan学习设计模式
工厂方法
?
简介:
上一篇我们介绍了简单工厂,还记得简单工厂的缺点么?忘了回去浏览一下(这里)!因为简单工厂创造了一个万能的上帝工厂类,它把所有的工作都包了。当我们增加一个新的产品的时候,我们仍需要修改工厂中的方法。而工厂方法改进了简单工厂这一缺点,并且保留了原有的优点。怎么做到的,继续看下去!
在工厂方法中,核心的工厂类摇身一变,变为一个抽象的工厂角色,而将具体的工作交给具体的子类去做。这个就是工厂方法对简单工厂的改进。言语表达不清,请看下面的类图。
?
UML类图:

?
还是类图比较直观。从类图中,我们看到,原来简单工厂的核心工厂类,变为了抽象工厂和继承它的具体工厂。产品现在都是由具体工厂来生产。每个具体工厂比较专心,生产一个产品,(当然,如果有必要,你可以让一个具体工厂生产多个产品)。实现请看下面的代码。
?
工厂方法的代码实现:
?
[java] view plaincopy
- interface AbstractProduct {
- }
- //具体产品1
- class Product1 implements AbstractProduct{
- public Product1(){
- System.out.println(生产具体产品1);
- }
- }
- //具体产品2
- class Product2 implements AbstractProduct{
- publicProduct2(){
- System.out.println(生产具体产品2);
- }
- }
- ?
- //抽象工厂,具体的实现交给实现该接口的具体工厂类去完成,
- interface AbstractFactory {
- public AbstractProduct create();
- }
- //具体工厂类1,主要生产具体产品1
- class Factory1 implements AbstractFactory{
- public AbstractProduct create() {
- return new Product1();
- }
- }
- //具体工厂类2,主要生产具体产品2
- class Factory2 implements AbstractFactory{
- public AbstractProduct create() {
- return new Product2();
- }
- }
- ?
- public class Main {
- public static void main(String[] args) {
- AbstractFactory factory = new Factory1();
- Product1 prodect1 = (Product1)factory.create();//生产了具体产品1
- ?
- factory = new Factory2();
- Product2 prodect2 = (Product2)factory.create();//生产了具体产品2
- }
- }
?
?
结构与角色:
抽象工厂(AbstractFactory)角色:担任这个角色的是工厂方法模式的核心,它是与应用程序无关的。任何在模式中创建对象的工厂类必须实现这个接口。在上面的系统中这个角色由接口Creator 扮演;在实际的系统中,这个角色也常常使用抽象类实现。
?
具体工厂(ConcreteFactory)角色:担任这个角色的是实现了抽象工厂接口的具体类。具体工厂角色含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。
在上面的例子中给出了两个这样的角色,也就是具体Java 类Factory1 和Factory2。
?
?
工厂方法模式的优点:
n 在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。这个核心类则摇身一变,成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节
n 这种进一步抽象化的结果,使这种工厂方法模式可以用来允许系统在不修改具体工厂角色的情况下引进新的产品
?
为什么要用工厂模式?
在上面一篇简单工厂中,没有体现出工厂模式的好处,所以在这里补充一下。
我们泡面来举例,并且正好这篇是工厂方法,所以,这里顺便体现一下工厂方法的优势。首先方便面有很多种类,有海鲜的,红烧的(我比较喜欢经典的红烧)等等。所以抽象一个方便面类InstantNoodle。
?

假设不考虑工厂,我们肚子饿了,要泡面,直接就泡了是不是。在代码中可能是下面这样:
?
[java] view plaincopy
- interface InstantNoodle{
- voidaddOil();//意思是加油
- voidaddPeiLiao();//意思是加配料,原谅我用汉字拼音表示
- }
- ?
- class HaiXian implements InstantNoodle{//意思是海鲜面
- publicHaiXian(){
- System.out.println(拆了一包海鲜面);
- }
- publicvoid addOil(){
- System.out.println(加了点油);
- }
- publicvoid addPeiLiao(){
- System.out.println(加了点海鲜风味的配料);
- }
- }
- ?
- class HongShao implements InstantNoodle{//意思是红烧面
- publicHongShao(){
- System.out.println(拆了一包红烧面);
- }
- publicvoid addOil(){
- System.out.println(加了点油,红烧面的油味道比较重哦!);
- }
- publicvoid addPeiLiao(){
- System.out.println(经典的红烧面配料);
- }
- }
- ?
- public class Main{
- publicstatic void main(String[] args){
- //假设现在肚子饿了,开始做面
- System.out.println(我要开始做红烧面了);
- InstantNoodlenoodle1=new HongShao();
- noodle1.addOil();
- noodle1.addPeiLiao();
- System.out.println(面做完了);
- System.out.println(-----------------------------------------------);
- ?
- //另外一个人想要吃海鲜面
- System.out.println(我要开始做海鲜面了);
- InstantNoodlenoodle2=new HaiXian();
- noodle2.addOil();
- noodle2.addPeiLiao();
- System.out.println(面做完了);
- System.out.println(-----------------------------------------------);
- ?
- }
- }
?
?
很麻烦是不是,每次做面,都要自己写一堆代码,这些事情包括加油啦,放配料啦,其实泡面不过就是一些流程,封装起来就好了,每次要吃面,直接告诉工厂,返回来给我就好了。所以简单工厂的实现是下面这样的。
?
[java] view plaincopy
- interface InstantNoodle{
- voidaddOil();//意思是加油