首页 > 代码库 > 设计模式——工厂方法

设计模式——工厂方法

 

目的

定义创建对象的方法/接口,然后让子类来决定创建具体的类的对象。

通过不同的类,使得实例化延迟至子类。

 

特点

必须引入继承,才能算是工厂方法模式。

 

Found in JDK API

java.util.Calendar#getInstance()
java.text.NumberFormat#getInstance()

java.lang.StringBuffer, java.lang.StringBuilder(继承自 AbstractStringBuilder)

 

变种

工厂方法是抽象的;

工厂方法有默认实现;

参数化工厂方法;

去掉Creator/Factory类,直接在类中定义工厂方法。

 

代码实现

Product是基类,子类包括MyProduct,YourProduct,DefaultProduct。

 

工厂方法是抽象的

package abs.factory;

import abs.domain.Product;

public abstract class ProductFactory {

    public abstract Product createProduct();
    
}


package abs.factory;

import abs.domain.MyProduct;
import abs.domain.Product;

public class MyProductFactory extends ProductFactory {

    @Override
    public Product createProduct() {
        return new MyProduct();
    }

}


package abs.factory;

import abs.domain.Product;
import abs.domain.YourProduct;

public class YourProductFactory extends ProductFactory {

    @Override
    public Product createProduct() {
        return new YourProduct();
    }

}

客户端调用

ProductFactory mpf = new MyProductFactory();
ProductFactory ypf = new YourProductFactory();

Product mp = mpf.createProduct();
Product yp = ypf.createProduct();

System.out.println(mp);
System.out.println(yp);

 

 

工厂方法有默认实现

public class ProductFactory {

    public Product createProduct() {
        return new MyProduct();
    }
    
}


public class YourProductFactory extends ProductFactory {

    @Override
    public Product createProduct() {
        return new YourProduct();
    }

}

客户端调用

ProductFactory pf = new ProductFactory();
ProductFactory ypf = new YourProductFactory();

Product mp = pf.createProduct();
Product yp = ypf.createProduct();

 

 

参数化工厂方法

public class ProductFactory {

    public Product createProduct() {
        return this.createProduct(null);
    }
    public Product createProduct(String productName) {
        if("my".equals(productName)) {
            return new MyProduct();            
        } else if("your".equals(productName)) {
            return new YourProduct();            
        }
        return new DefaultProduct();
    }
    
}

 

客户端调用

ProductFactory pf = new ProductFactory();
Product myProduct = pf.createProduct("my");
Product yourProduct = pf.createProduct("your");
Product defaultProduct = pf.createProduct();

 

 

去掉Creator/Factory类,直接在类中定义工厂方法

通常结合静态化的参数化工厂方法的方式来实现

public class Product {

    protected Product() {
        
    }
    public static Product getInstance() {
        return getInstance(null);
    }
public static Product getInstance(String productName) { if("my".equals(productName)) { return new MyProduct(); } else if("your".equals(productName)) { return new YourProduct(); } return new DefaultProduct(); } }

客户端调用

Product myProduct = Product.getInstance("my");
Product yourProduct = Product.getInstance("your");
Product defaultProduct = Product.getInstance();

 

 

JDK API应用场景:java.util.Calendar

public class Calendar {

protected Calendar()
    {
        this(TimeZone.getDefaultRef(), Locale.getDefault());
    sharedZone = true;
    }

public static Calendar getInstance() { Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault()); cal.sharedZone = true; return cal; } public static Calendar getInstance(TimeZone zone) { return createCalendar(zone, Locale.getDefault()); } public static Calendar getInstance(Locale aLocale) { Calendar cal = createCalendar(TimeZone.getDefaultRef(), aLocale); cal.sharedZone = true; return cal; } public static Calendar getInstance(TimeZone zone, Locale aLocale) { return createCalendar(zone, aLocale); } private static Calendar createCalendar(TimeZone zone, Locale aLocale) { // If the specified locale is a Thai locale, returns a BuddhistCalendar // instance. if ("th".equals(aLocale.getLanguage()) && ("TH".equals(aLocale.getCountry()))) { return new sun.util.BuddhistCalendar(zone, aLocale); } else if ("JP".equals(aLocale.getVariant()) && "JP".equals(aLocale.getCountry()) && "ja".equals(aLocale.getLanguage())) { return new JapaneseImperialCalendar(zone, aLocale); } // else create the default calendar return new GregorianCalendar(zone, aLocale); } }