设计模式之禅学习——工厂方法模式
工厂方法模式——定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
一、工厂方法模式的通用代码:
首先要定义产品族,也就是一个产品的接口
package com.wang.factoryPattern.method;
/**
* 产品类接口
* @author HeJW
*
*/
public interface Product {
public void method1();
public String method2(String args);
}
然后,让我们定义两个实现该接口的类,也就是具体的产品:
第一个产品:
package com.wang.factoryPattern.method;
/**
* 具体产品类1
* @author HeJW
*
*/
public class ConcreteProduct1 implements Product {
public ConcreteProduct1(){
System.out.println("ConcreteProduct1 被创建");
}
@Override
public void method1() {
System.out.println("xx");
}
@Override
public String method2(String args) {
return args;
}
}
第二个产品,代码与第一个产品基本相同:
package com.wang.factoryPattern.method;
/**
* 具体产品类2
* @author HeJW
*
*/
public class ConcreteProduct2 implements Product {
public ConcreteProduct2(){
System.out.println("ConcreteProduct2 被创建");
}
@Override
public void method1() {
System.out.println("yy");
}
@Override
public String method2(String args) {
return args;
}
}
现在该定义工厂方法的工厂接口了:
package com.wang.factoryPattern.method;
/**
* 工厂方法的接口
* @author HeJW
*
*/
public interface Factory {
/*
* 创建一个产品对象,其输入参数类型可以自行设置
* 通常为String、Enum、Class等,当然也可以为空
*/
//输入类型为Class
public <T extends Product> T productFactory1(Class<T> c);
//输入类型为String
public Product productFactory2(String product);
}
之后,实现该工厂接口:
package com.wang.factoryPattern.method;
/**
* 具体工厂类
* @author HeJW
*
*/
public class ConcreteFactory implements Factory {
@Override
public <T extends Product> T productFactory1(Class<T> c) {
Product product1 = null;
try {
product1 = (Product)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
//异常处理
}
return (T)product1;
}
@Override
public Product productFactory2(String product) {
Product product2 = null;
if( product.equals("ConcreteProduct1") ){
product2 = new ConcreteProduct1();
} else {
product2 = new ConcreteProduct2();
}
return product2;
}
}
现在工厂方法模式已经实现了,下面编写一个测试类,看看工厂方法模式的使用:
package com.wang.factoryPattern.method;
/**
* 测试类
* @author HeJW
*
*/
public class App {
public static void main(String[] args) {
Factory factory = new ConcreteFactory();
ConcreteProduct1 product1 = factory.productFactory1(ConcreteProduct1.class);
product1.method1();
ConcreteProduct2 product2 = (ConcreteProduct2) factory.productFactory2("ConcreteProduct2");
product2.method1();
}
}
运行结果如下:
二、工厂方法模式的扩展
1、工厂方法模式向下缩小为简单工厂模式,
简单工厂模式的工厂类代码如下:
package com.wang.factoryPattern.simple;
import com.wang.factoryPattern.method.Product;
/**
* 简单工厂类
* 就是加了个static
* @author HeJW
*
*/
public class SimpleFactory {
public static <T extends Product> T productFactory( Class<T> c ){
Product product = null;
try {
product = (Product)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T)product;
}
}
非常简单,下面编写一个测试类,看看简单工厂模式的使用:
package com.wang.factoryPattern.simple;
import com.wang.factoryPattern.method.ConcreteProduct1;
/**
* 简单工厂测试类
* @author HeJW
*
*/
public class App {
public static void main(String[] args) {
ConcreteProduct1 product1 = SimpleFactory.productFactory(ConcreteProduct1.class);
product1.method1();
}
}
2、工厂方法模式向上扩展为多工厂模式,所谓多工厂模式,就是为具体的每一个产品类,都有专门的工厂方法,该工厂方法,只能生产指定的某一产品。
多工厂模式的工厂接口:
package com.wang.factoryPattern.many;
import com.wang.factoryPattern.method.Product;
/**
* 多工厂模型的工厂接口
* @author HeJW
*
*/
public interface ProductFacory {
public Product productFactory();
}
产品1的工厂方法:
package com.wang.factoryPattern.many;
import com.wang.factoryPattern.method.ConcreteProduct1;
import com.wang.factoryPattern.method.Product;
/**
* ConcreteProduct1工厂的实现类
* @author HeJW
*
*/
public class ConcreteProduct1Factory implements ProductFacory {
@Override
public Product productFactory() {
return new ConcreteProduct1();
}
}
产品2的工厂方法:
package com.wang.factoryPattern.many;
import com.wang.factoryPattern.method.ConcreteProduct2;
import com.wang.factoryPattern.method.Product;
/**
* ConcreteProduct2工厂的实现类
* @author HeJW
*
*/
public class ConcreteProduct2Factory implements ProductFacory {
@Override
public Product productFactory() {
return new ConcreteProduct2();
}
}
现在已经为产品1和产品2定制了专门的工厂,现在我们看看多工厂模式的使用:
package com.wang.factoryPattern.many;
import com.wang.factoryPattern.method.ConcreteProduct1;
public class App {
public static void main(String[] args) {
ProductFacory factory = new ConcreteProduct1Factory();
ConcreteProduct1 product1 = (ConcreteProduct1) factory.productFactory();
product1.method1();
}
}
3、使用工厂方法模式替代单例模式,使用的是一些反射的知识。
首先先建立一个符合单例模式的单例类:
package com.wang.factoryPattern.singleton;
/**
* 单例类
* @author HeJW
*
*/
public class Singleton {
private Singleton(){
//不允许通过New,产生一个对象
System.out.println("singleton 创建");
};
public void method(){
System.out.println("singleton 输出");
}
}
然后为这个单例类创建它的工厂方法:
package com.wang.factoryPattern.singleton;
import java.lang.reflect.Constructor;
/**
* 替代单例模式的工厂类
* @author HeJW
*
*/
public class SingletonFactory {
private static Singleton singleton;
static{
try{
Class c1 = Class.forName(Singleton.class.getName());
//获得无参构造函数
Constructor constructor = c1.getDeclaredConstructor();
//设置无参构造函数是可访问的
constructor.setAccessible(true);
//产生一个实例对象
singleton = (Singleton) constructor.newInstance();
} catch( Exception e ){
//异常处理
}
}
public static Singleton getSingleton(){
return singleton;
}
}
编写一个测试类,来看看单例类是不是只被创建的一次:
package com.wang.factoryPattern.singleton;
public class App {
public static void main(String[] args) {
Singleton singleton1 = SingletonFactory.getSingleton();
singleton1.method();
Singleton singleton2 = SingletonFactory.getSingleton();
singleton2.method();
}
}
运行结果如下:
4、使用工厂方法模式实现类的延时初始化
意思就是如果这个产品没有被创建或者已经被销毁,那么就创建一个;如果在程序运行中,已经有了实例对象,那么就直接用这个实例对象,代码如下:
package com.wang.factoryPattern.lazy;
import java.util.HashMap;
import java.util.Map;
import com.wang.factoryPattern.method.ConcreteProduct1;
import com.wang.factoryPattern.method.ConcreteProduct2;
import com.wang.factoryPattern.method.Product;
/**
* 延时初始化的工厂类
* @author HeJW
*
*/
public class LazyProductFactory {
private static final Map<String, Product> prMap = new HashMap<String, Product>();
public static synchronized Product ProductFactory(String type){
Product product = null;
//如果Map中已经有这个对象
if ( prMap.containsKey(type) ) {
product = prMap.get(type);
} else {
if( type.equals("ConcreteProduct1") ){
product = new ConcreteProduct1();
} else if (type.equals("ConcreteProduct2")) {
product = new ConcreteProduct2();
}
//同时把对象放到缓存容器中
prMap.put(type, product);
}
return product;
}
}
测试类代码如下:
package com.wang.factoryPattern.lazy;
import com.wang.factoryPattern.method.ConcreteProduct1;
public class App {
public static void main(String[] args) {
ConcreteProduct1 product1 = (ConcreteProduct1) LazyProductFactory.ProductFactory("ConcreteProduct1");
product1.method1();
//当此次创建ConcreteProduct1时,是从map中取出的。
ConcreteProduct1 product2 = (ConcreteProduct1) LazyProductFactory.ProductFactory("ConcreteProduct1");
product2.method1();
}
}
运行结果如下: