欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

工厂方法模式及其扩展

程序员文章站 2022-04-04 15:04:43
...

设计模式之禅学习——工厂方法模式

 

工厂方法模式——定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。

 

一、工厂方法模式的通用代码:

首先要定义产品族,也就是一个产品的接口

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();
	}
	
}	

 运行结果如下:


工厂方法模式及其扩展
            
    
    博客分类: DesignPattern 设计模式工厂方法 
 

二、工厂方法模式的扩展

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();
	}
	
}

 运行结果如下:

工厂方法模式及其扩展
            
    
    博客分类: DesignPattern 设计模式工厂方法 
 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();
	}
	
}

 运行结果如下:


工厂方法模式及其扩展
            
    
    博客分类: DesignPattern 设计模式工厂方法 
 

  • 工厂方法模式及其扩展
            
    
    博客分类: DesignPattern 设计模式工厂方法 
  • 大小: 11 KB
  • 工厂方法模式及其扩展
            
    
    博客分类: DesignPattern 设计模式工厂方法 
  • 大小: 31.7 KB
  • 工厂方法模式及其扩展
            
    
    博客分类: DesignPattern 设计模式工厂方法 
  • 大小: 34.5 KB