目录
背景
工厂模式实际开发中用到很多,网上的介绍案例非常多。工厂模式存在一些问题:
使用工厂前:我们有一系列的产品类,都有共同的父类。这种情况才会想到工厂。
简单工厂
定义:专门定义一个类来负责创建产品对象(根据唯一标识分发)
优点:简单
缺点:耦合度高,如果有变动就需要修改唯一的工厂的入口方法。
工厂方法
定义:专门定义一个用于创建产品对象接口,子工厂类去决定,实例化具体产品类。每个产品都有自己的工厂。
本质:就是把简单工厂的方法抽象了,具体产品都要去实现各自的工厂。解决简单工厂缺点。这样服务端新增产品,不需要改代码。只需新增,产品,和其对应的工厂。
优点:符合开闭原则(具体的业务类有具体工厂),
缺点:每增加一个产品,相应的也要增加一个子工厂,加大了额外的开发量。但是实际开发中,客户端也不会去主动找工厂的啊,这就好比你买手机,你买苹果手机去苹果官网买,买华为去华为商城买。我再想买小米,又要搞一个小米的商城,才能买手机。这确实是扩展性好。实际中我们是通过一个入口去买更方便,这才是用户比较迫切的需求,就比如,我在京东,输入苹果,就买买到苹果,输入华为就能买到华为了。所以工厂方法我觉得存在的问题复杂了,回归本初,回到最初简单工厂思想:通过一个唯一入口,根据不同的参数,即可获得具体的业务类。
需求
实现一个网关,路由不同的渠道。考虑扩展,符合开闭原则,怎么才能写好符合开闭的工厂呢?
开闭原则:就是说对扩展开放,对修改关闭。
分析
我们要设计的网关,来路由不同的业务类,要满足的条件:
1.开闭原则必须满足;
2.工厂类提供唯一入口分发;避免新增业务增加新的工厂代码量
3.具体业务类且只需要实现自己的业务,其他的一概不需要关心。业务类扩展性好,且不用修改工厂类,或者增加工厂。
代码
使用的开发环境:springboot、jdk1.8
抽象一个造手机的工厂业务
1.工厂类
public class JdMallFactory {
private static Map<String, Phone> map = new HashMap<>();
public static Phone getPhoneService(String phoneName){
return map.get(phoneName);
}
public static void addPhoneService(String phoneName, Phone phone) {
map.put(phoneName, phone);
}
}
2.业务类
1)枚举:业务名唯一标示
public enum PhoneNameEnum {
apple,huawei,xiaomi
}
2)接口:定义业务功能
public interface Phone {
void call();
}
3)抽象类:具体业务和工厂合作抽象模版化,后续业务类不需要关心,继承此类即可
public abstract class AbstractPhone implements Phone {
abstract String getPhoneName();
@PostConstruct
public void providePhoneToFactory() {
JdMallFactory.addPhoneService(getPhoneName(), this);
}
}
4)业务扩展类,华为手机
public class HuaWeiService extends AbstractPhone {
@Override
public String getPhoneName() {
return PhoneNameEnum.huawei.name();
}
@Override
public void call() {
System.out.println(getPhoneName() + "增加定制功能");
System.out.println("使用" + getPhoneName() + "打电话");
}
}
5)业务扩展类,苹果手机
public class AppleService extends AbstractPhone {
@Override
public String getPhoneName() {
return PhoneNameEnum.apple.name();
}
@Override
public void call() {
System.out.println(getPhoneName() + "增加定制功能");
System.out.println("使用" + getPhoneName() + "打电话");
}
}
3.客户端
public class FactoryTest {
@Test
public void testFactory() {
// 1、模拟服务端启动,华为和苹果公司成立。(使用Spring框架,这一步使用组件注入到IOC即可,不用new)
new HuaWeiService();
new AppleService();
// 2、模拟客户端:用户买手机(京东商城买手机)
Phone phoneService = JdMallFactory.getPhoneService(PhoneNameEnum.huawei.name());
// 用户使用手机
phoneService.call();
phoneService = JdMallFactory.getPhoneService(PhoneNameEnum.apple.name());
phoneService.call();
}
}
测试输出:
huawei增加定制功能
使用huawei打电话
apple增加定制功能
使用apple打电话
总结
以上代码实现,可以看出是满足我们想法的:
1.开闭原则必须满足;- 满足
2.工厂类提供唯一入口分发;避免新增业务增加新的工厂代码量。- 满足
3.具体业务类且只需要实现自己的业务,其他的一概不需要关心。业务类扩展性好,且不用修改工厂类,或者增加工厂。- 满足