目录
1、简介
简单工厂模式(Simple Factory)又称为静态工厂方法模式(Static Factory Method)。简单工厂模式简单来说就是根据参数的不同返回不同类的实例。
2、特点
- 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
3、代码演示
3.1、类图
3.2、代码
3.2.1、PayService
package com.inconspicuousy.pattern.simplefactory;
/**
* 支付基类
* @author inconspicuousy
*/
public interface PayService {
/** 支付 */
void doPay();
}
3.2.2、AliPayService
package com.inconspicuousy.pattern.simplefactory;
/**
* 支付宝支付
* @author inconspicuousy
*/
public class AliPayService implements PayService {
@Override
public void doPay() {
System.out.println("使用支付宝支付");
}
}
3.2.3、WeiXinPayService
package com.inconspicuousy.pattern.simplefactory;
/**
* 微信支付
* @author inconspicuousy
*/
public class WeiXinPayService implements PayService {
@Override
public void doPay() {
System.out.println("使用微信支付");
}
}
3.2.4、PayServiceFactory
package com.inconspicuousy.pattern.simplefactory;
/**
* 提供简单支付工厂类, 为用户选择指定的支付方式
*
* 简单工厂又叫静态工厂
* @author inconspicuousy
*/
public class PayServiceFactory {
/**
* 根据二维码链接获取到实际的支付方式
*
* 什么是简单工厂模式?
* 实际上就是根据用户的某个行为创建指定的对象,
* 将创建对象的方式作集中处理, 每次如果要对支付方式扩展,只需要针对简单工厂类进行修改,
* 调用者不需要做修改, 符合OCP原则
*
* @param qrCodeUrl 用户选择的支付方式, 用来区分支付宝还是微信
* @return 返回实际的支付方式
*/
public static PayService getPayService(String qrCodeUrl) {
if (qrCodeUrl.startsWith("alipay")) {
return new AliPayService();
}
if (qrCodeUrl.startsWith("weixin")) {
return new WeiXinPayService();
}
System.out.println("当前没有可用的支付方式");
return null;
}
}
3.2.5、Store
package com.inconspicuousy.pattern.simplefactory;
/**
* 店铺就是当前的客户端, 用来为用户提供二维码链接
*
* 测试简单工厂
* @author inconspicuousy
*/
public class Store {
public static void main(String[] args) {
String qrCodeUrl = "alipay://xxx";
// 所有的店铺都只是通过二维码获取到支付方式
// 当需要扩展支付方式时时不需要商店作出改变, 改变简单工厂就行
PayService payService = PayServiceFactory.getPayService(qrCodeUrl);
if (payService != null) {
// 使用支付宝支付
payService.doPay();
}
}
}
4、优缺点
4.1、优点
简单易于实现,把类的实例化交给工厂,易于解耦
4.2、缺点
违反开闭原则,不利于扩展和维护(没增加一个支付方式就需要修改工厂的方法)
4.3、如何去解决简单工厂的问题呢?
- 将对象的名称和对象通过配置文件(xml)进行配置,读取到内存中建立映射关系(Map集合,注意:使用修改配置文件不算违反开闭原则,配置文件不需要编译)
- 直接在工厂类中加一个map集合,key为bean名称,value是bean对象,最后加一个从map集合中获取bean的方法,并且在启动时就将所有实现类的bean对象加载到map集合中
这里使用解决方案二演示:
接口:
package com.kgf.factory.simple.inter; /** * 支付基类 * @author inconspicuousy */ public interface PayService { /** 支付 */ void doPay(); }
AliPayService
package com.kgf.factory.simple.inter.impl; import com.kgf.factory.simple.inter.PayService; import org.springframework.stereotype.Service; /** * 支付宝支付 * @author inconspicuousy */ @Service public class AliPayService implements PayService { @Override public void doPay() { System.out.println("使用支付宝支付"); } }
WeiXinPayService
package com.kgf.factory.simple.inter.impl; import com.kgf.factory.simple.inter.PayService; import org.springframework.stereotype.Service; /** * 微信支付 * @author inconspicuousy */ @Service public class WeiXinPayService implements PayService { @Override public void doPay() { System.out.println("使用微信支付"); } }
PayServiceFactory
package com.kgf.factory.simple.factory; import com.kgf.factory.simple.inter.PayService; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.util.Map; /** * 提供简单支付工厂类, 为用户选择指定的支付方式 * * 简单工厂又叫静态工厂 * @author inconspicuousy */ @Component public class PayServiceFactory implements ApplicationContextAware { private static Map<String,PayService> payServiceMap; /*** * 直接将所有实现PayService的实现类对象获取 * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.payServiceMap = applicationContext.getBeansOfType(PayService.class); } /** * 根据二维码链接获取到实际的支付方式 * * 什么是简单工厂模式? * 实际上就是根据用户的某个行为创建指定的对象, * 将创建对象的方式作集中处理, 每次如果要对支付方式扩展,只需要针对简单工厂类进行修改, * 调用者不需要做修改, 符合OCP原则 * * @param beanName 用户选择的支付方式的bean对象名称,用来区分支付宝还是微信 * @return 返回实际的支付方式 */ public static PayService getPayService(String beanName) { PayService payService = payServiceMap.get(beanName); if (payService!=null){ return payService; } System.out.println("当前没有可用的支付方式"); return null; } }
测试代码:
package com.kgf.factory.simple; import com.kgf.factory.FactoryApplication; import com.kgf.factory.simple.factory.PayServiceFactory; import com.kgf.factory.simple.inter.PayService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(classes = FactoryApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class FactoryPatternTest { @Test public void SimpleFactoryTest(){ PayService payService = PayServiceFactory.getPayService("aliPayService"); if (payService != null) { // 使用支付宝支付 payService.doPay(); } } }
效果:
使用环境
- 工厂类负责创建的对象比较少的情况适合使用。创建的对象较少,不会造成工厂方法中业务逻辑太过复杂。