简单工厂模式有一个缺点,就是当有新产品要加入进来的时候就得修改服务端原有代码。为了弥补简单工厂的不足,于是有了工厂方法模式。

工厂方法模式把工厂也抽像出来,一个具体的产品有一个相应的具体工厂。

下面是一个简单的例子。一个手机厂商需要生产手机。刚开始他们只生产华为手机,后来新增生产中兴手机,有可能后续还会生产更多品种的手机。文档结构如下:

| |-Client.java
| |-Factory.java
| |-factory.properties
| |-HuaWeiFactory.java
| |-HuaWeiPhone.java
| |-Phone.java
| |-PropertyUtil.java
| |-ZTEFactory.java
| `-ZTEPhone.java

抽像工厂Factory.java

public interface Factory{
    void initFactory();
    Phone createPhone();
}

抽像产品Phone.java

public interface Phone{
    void display();
}

具体产品华为手机HuaWeiPhone.java

public class HuaWeiPhone implements Phone{
    public void display(){
        System.out.println("HuaWeiPhone");
    }
}

具体产品中兴手机ZTEPhone.java

public class ZTEPhone implements Phone{
    public void display(){
        System.out.println("ZTEPhone");
    }
}

具体华为手机工厂HuaWeiFactory.java

public class HuaWeiFactory implements Factory{
    public void initFactory(){}

    public Phone createPhone(){
        Phone phone = new HuaWeiPhone();
        return phone;
    }
}

具体的中兴手机工厂ZTEFactory.java

public class ZTEFactory implements Factory{
    public void initFactory(){}

    public Phone createPhone(){
        Phone phone = new ZTEPhone();
        return phone;
    }
}

客户端的配置文件factory.properties

className=ZTEFactory

客户端配置文件读取类PropertyUtil.java

import java.io.*;
import java.util.*;
public class PropertyUtil{
    public static Object getBean(){
        Object obj = null;
        try{
            Properties prop = new Properties();
            InputStream in = new BufferedInputStream(new FileInputStream("factory.properties"));
            prop.load(in);
            String className = prop.getProperty("className");
            Class c = Class.forName(className);
            obj = c.newInstance();
        }catch(Exception e){
            //Exception
            e.printStackTrace();
        }
        return obj;
    }
}

客户端Client.java

public class Client{
    public static void main(String args[]){
        //Factory factory = new HuaWeiFactory();
        Factory factory = (Factory)PropertyUtil.getBean();
        Phone phone = factory.createPhone();
        phone.display();
    }
}

(完)