Java设计模式及应用场景之《简单工厂模式》

文章目录

        • 一、简单工厂模式定义
        • 二、简单工厂模式的结构和说明
        • 三、简单工厂模式示例
        • 四、可配置的简单工厂模式示例
        • 五、简单工厂模式的优缺点
        • 六、简单工厂模式的应用场景

一、简单工厂模式定义

简单工厂提供了一个创建对象实例的功能,而无需关心其具体实现。被创建对象实例的类型可以是抽象类、接口,也可以是具体的类。

二、简单工厂模式的结构和说明

Java设计模式及应用场景之《简单工厂模式》_第1张图片

  • Api: 定义所需要的功能接口。
  • ApiImplA、ApiImplB: Api接口的实现类,可能会有更多个。
  • Factory: 工厂类,根据条件选择合适的实现类来创建Api的对象。

三、简单工厂模式示例

  假设有一个订单支付功能,我们有两种支付方式,一种支付宝支付,一种微信支付。用户在客户端进行支付的时候,需要从这两种支付方式中选取一种,来进行支付操作。

首先我们有一个支付接口:

/**
 * 支付接口
 */
public interface Pay {

	/**
	 * 支付操作方法
	 */
	public void pay();
}

然后我们有两个具体支付业务类:

/**
 * 支付宝支付
 */
public class ZhiFuBaoPay implements Pay {

	@Override
	public void pay() {
		System.out.println("通过支付宝进行支付...");
	}

}
/**
 * 微信支付
 */
public class WeiXinPay implements Pay {

	@Override
	public void pay() {
		System.out.println("通过微信进行支付...");
	}

}

定义工厂类:

/**
 * 工厂类,用来创造具体支付业务对象
 */
public class PayFactory {
	
	private PayFactory() {} // 防止客户端无谓的创建工厂实例,将构造方法私有化

	/**
	 * 具体的创造支付业务对象实例的方法
	 * @param type 从外部传入的选择条件
	 * @return
	 */
	public static Pay createPay(String type){
		//应该根据某些条件去选择究竟创建哪一个具体的实现对象
		//这些条件可以从外部传入,也可以从其它途径获取
		//如果只有一个实现,可以省略条件,因为没有选择的必要
		
		Pay pay = null;
		if("ZFB".equals(type)){
			pay = new ZhiFuBaoPay();
		}else if("WX".equals(type)){
			pay = new WeiXinPay();
		}else{
			System.out.println("支付方式不正确");
		}
		
		return pay;
	}
	
}

那么我们在客户端用的时候,就可以这样用:

public static void main(String[] args) {
		
	Pay pay = PayFactory.createPay("ZFB");
	pay.pay();// 输出:通过支付宝进行支付...
		
}

四、可配置的简单工厂模式示例

  如果我们新增一种支付方式的话,通过上边说的模式,我们就需要修改工厂类:

/**
 * 具体的创造支付业务对象实例的方法
 * @param type 从外部传入的选择条件
 * @return
 */
public static Pay createPay(String type){
	//应该根据某些条件去选择究竟创建哪一个具体的实现对象
	//这些条件可以从外部传入,也可以从其它途径获取
	//如果只有一个实现,可以省略条件,因为没有选择的必要
	
	Pay pay = null;
	if("ZFB".equals(type)){
		pay = new ZhiFuBaoPay();
	}else if("WX".equals(type)){
		pay = new WeiXinPay();
	}
	// 新增银联支付方式
	else if("YL".equals(type)){
		pay = new YinLianPay();
	}
	else{
		System.out.println("支付方式不正确");
	}
	
	return pay;
}

这样肯定不是一个好的实现方式。一个解决的方法就是,将具体的实现类配置到配置文件中,在简单工厂的方法里面通过反射来获取实现类。

配置文件中:
ZFB=com.pay.ZhiFuBaoPay WX=com.pay.WeiXinPay YL=com.pay.YinLianPay

我们的工厂类方法可以这样实现:

/**
 1. 具体的创造支付业务对象实例的方法
 2. @param type 从外部传入的选择条件
 3. @return
 */
public static Pay createPay(String type){
	//应该根据某些条件去选择究竟创建哪一个具体的实现对象
	//这些条件可以从外部传入,也可以从其它途径获取
	//如果只有一个实现,可以省略条件,因为没有选择的必要
	
	// 读取配置文件的内容,这里不介绍怎么读取配置文件了
	String payClazzName = getProperty(type);
	
	Pay pay = null;
	//用反射去创建具体对象实例
	try {
		pay = (Pay)Class.forName(payClazzName).newInstance();
	} catch (InstantiationException e) {
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		e.printStackTrace();
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	}
	
	return pay;
}

五、简单工厂模式的优缺点

优点:

  • 帮助封装。 简单工厂虽然很简单,但是非常友好的帮助我们实现了组件的封装,让组件外部真正能实现面向接口编程。
  • 解耦。 通过简单工厂,实现了调用类和具体实现类的解耦。

缺点:

  • 可能增加客户端的复杂度。 如果通过客户端传过来的参数来选择具体的实现类,就必须要求客户端理解各个参数代表的含义,这样会增加客户端的复杂度。

六、简单工厂模式的应用场景

  • 如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装类,那么可以选择简单工厂模式。
  • 如果想要把对外创建对象的职责集中管理和控制,可以选择简单工厂模式。

你可能感兴趣的:(Java设计模式)