源码:https://github.com/GiraffePeng/design-patterns/tree/master/factory-pattern
1、设计原则
为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据7条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。
而设计模式都是在设计原则中不断的学习总结得出的模式概念,七大设计原则包括:
设计原则 | 解释 |
---|---|
开闭原则 | 对修改关闭,对拓展开放,要求我们在设计类、接口、方法时,注重其可拓展性,尽量不要在原有代码基础上去二次修改或变更 |
依赖倒置原则 | 高层模块不应该依赖于底层模块,他们都应依赖于抽象模块,细节依赖抽象,抽象不依赖细节,要求我们在设计程序时,注重面向抽象开发,使用抽象概念来使各个类或者模块互不影响,实现松耦合 |
单一职责原则 | 一个接口、类或者方法只做一件事,如果其能够完成多件事,会因为职责过重导致提高了复杂度、降低了可读性,从而考虑拆分 |
接口隔离原则 | 注重接口的设计粒度,一个客户端不应该去实现其不需要的接口,接口的设计不应该太臃肿 |
迪米特原则 | 又称最少知识原则,从依赖者的角度来说,只依赖应该依赖的对象,从被依赖者的角度说,只暴露应该暴露的方法 |
里氏替换原则 | 发生于父类与子类之间,子类可以拓展父类的功能但不能改变父类原有的功能,对于调用者来说,调用父类的功能如果替换成其子类功能,实现的效果或者达到的目的是一致的 |
合成复用原则 | 尽量使用对象组合、聚合,而不使用继承关系达到代码复用的目的。 |
2、学习设计模式的好处
举个生活中的有趣的例子,某次公司团建,喝酒+唱歌,开心乐逍遥,于是乎发出了【喝酒唱歌,人生真爽】的感叹。
当你学了设计模式之后,可能觉得刚才的话有些low,稍加改造也许会变成这样,【对酒当歌,人生几何】。
于是乎引出学习设计模式的好处在于:
- 能够写出优雅的代码,能够有拓展性、可读性、层次性。
- 能够帮助我们更好的重构代码逻辑,重构项目。
- 优秀中的源码中也用到了许许多多设计模式,方便我们能更好的去阅读源码
比如Spring中的设计模式的体现:
设计模式名称 | 举例 |
---|---|
工厂模式 | BeanFactory |
装饰器模式 | BeanWrapper |
代理模式 | AopProxy |
委派模式 | DispatcherServlet |
策略模式 | HandlerMapping |
适配器模式 | HandlerAdapter |
模板模式 | JdbcTemplate |
观察者模式 | ContextLoaderListener |
需要特别声明的是,设计模式从来都不是单个设计模式独立使用的。在实际应用中,通常是多个设计模式混合使用,你中有我,我中有你。
3、工厂模式
3.1 简单工厂模式
简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类的实例,但它不属于23 种设计模式。
简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心。
我们以手机制造为例,常见的品牌有华为、Apple、Samsung、小米等,我们定义一个IPhone接口:
package com.peng.simplefactory;
//手机接口
public interface IPhone {
public void createPhone();
}
创建一个手机的实现ApplePhone类:
package com.peng.simplefactory;
public class ApplePhone implements IPhone{
@Override
public void createPhone() {
System.out.println("创建苹果手机");
}
}
看客户端调用代码,我们会这样写:
package com.peng.simplefactory;
public class SimplefactoryTest {
public static void main(String[] args) {
IPhone phone = new ApplePhone();
phone.createPhone();
}
}
看上面的代码,父类 IPhone 指向子类 ApplePhone 的引用,应用层代码需要依赖ApplePhone,如果业务扩展,我继续增加 HuaweiPhone 甚至更多,那么我们客户端的依赖会变得越来越臃肿。因此,我们要想办法把这种依赖减弱,把创建细节隐藏。虽然目前的代码中,我们创建对象的过程并不复杂,但从代码设计角度来讲不易于扩展。现在,我们用简单工厂模式对代码进行优化。先增加华为手机类:
package com.peng.simplefactory;
public class HuaweiPhone implements IPhone{
@Override
public void createPhone() {
System.out.println("创建华为手机");
}
}
创建 SimplePhoneFactory 工厂类:
package com.peng.simplefactory;
public class SimplePhoneFactory {
public static IPhone createPhoneFactory(String phoneType) {
IPhone iphone = null;
if("apple".equals(phoneType)) {
iphone = new ApplePhone();
}else if("huawei".equals(phoneType)) {
iphone = new HuaweiPhone();
}
return iphone;
}
}
修改客户端调用代码:
package com.peng.simplefactory;
public class SimplefactoryTest {
public static void main(String[] args) {
IPhone phone = SimplePhoneFactory.createPhoneFactory("apple");
phone.createPhone();
}
}
下面来看一下类图
客户端调用是简单了,但如果我们业务继续扩展,要增加前端课程,那么工厂中的 createPhoneFactory()就要根据产品链的丰富每次都要修改代码逻辑。不符合开闭原则。因此,我们对简单工厂还可以继续优化,可以采用反射技术:
package com.peng.simplefactory;
public class SimplePhoneFactory {
//代理实现
public static IPhone createPhoneFactoryReflex(String className) {
IPhone iphone = null;
if(className != null && className != "") {
try {
iphone = (IPhone) Class.forName(className).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
}
return iphone;
}
}
修改客户端调用代码:
package com.peng.simplefactory;
public class SimplefactoryTest {
public static void main(String[] args) {
IPhone phone = SimplePhoneFactory.createPhoneFactoryReflex("com.peng.simplefactory.ApplePhone");
phone.createPhone();
}
}
优化之后,产品不断丰富不需要修改 SimplePhoneFactory 中的代码。但是,有个问题是,方法参数是字符串,可控性有待提升,而且还需要强制转型。我们再修改一下代码:
package com.peng.simplefactory;
public class SimplePhoneFactory {
// 代理实现
public static IPhone createPhoneFactoryReflexByClass(Class<? extends IPhone> clazz) {
IPhone iphone = null;
if (clazz != null) {
try {
iphone = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
return iphone;
}
}
优化客户端代码:
package com.peng.simplefactory;
public class SimplefactoryTest {
public static void main(String[] args) {
IPhone phone = SimplePhoneFactory.createPhoneFactoryReflexByClass(ApplePhone.class);
phone.createPhone();
}
}
再看一下类图
简单工厂模式在JDK源码中也会存在,比如时间操作类Calendar,看Calendar.getInstance()方法:
public static Calendar getInstance()
{
Locale aLocale = Locale.getDefault(Locale.Category.FORMAT);
return createCalendar(defaultTimeZone(aLocale), aLocale);
}
下面打开createCalendar的具体创建类的方法,关键点用注释已标出
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
## 这里使用了简单工厂模式,根据传入的caltype来判断创建哪一种类型的Calender实例
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
## 这里使用了简单工厂模式,根据判断参数来创建哪一种类型的Calender实例
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
简单工厂模式也有其缺点:工厂类的职责过重,不易于扩展复杂的业务场景。当使用的不为反射机制处理的简单工厂模式时,如果新加入的产品,还需要修改工厂的创建方法,不符合开闭原则。
3.2 工厂方法模式
工厂方法模式(Fatory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。
工厂方法模式主要解决产品扩展的问题,在简单工厂中,随着产品链的丰富,如果每个手机的创建逻辑有区别的话,工厂的职责会变得越来越多,有点像万能工厂,并不便于维护。根据单一职责原则我们将职能继续拆分,专人干专事。Apple手机由 Apple 工厂创建,Huawei手机由 Huawei工厂创建,对工厂本身也做一个抽象。来看代码,先创建IPhoneFactory 接口:
package com.peng.factory;
import com.peng.IPhone;
public interface IPhoneFactory {
public IPhone createPhoneByFactory();
}
然后通过实现IPhoneFactory接口,来创建Apple以及Huawei的工厂类:
package com.peng.factory;
import com.peng.ApplePhone;
import com.peng.IPhone;
//苹果工厂类
public class ApplePhoneFactory implements IPhoneFactory{
@Override
public IPhone createPhoneByFactory() {
return new ApplePhone();
}
}
package com.peng.factory;
import com.peng.HuaweiPhone;
import com.peng.IPhone;
//华为工厂类
public class HuaweiPhoneFactory implements IPhoneFactory{
@Override
public IPhone createPhoneByFactory() {
return new HuaweiPhone();
}
}
创建测试类:
package com.peng.factory;
import com.peng.IPhone;
public class FactoryTest {
public static void main(String[] args) {
//创建苹果实例
IPhoneFactory appleFactory = new ApplePhoneFactory();
IPhone applePhone = appleFactory.createPhoneByFactory();
applePhone.createPhone();
//创建华为实例
IPhoneFactory huaweiFactory = new HuaweiPhoneFactory();
IPhone huaweiPhone = huaweiFactory.createPhoneByFactory();
huaweiPhone.createPhone();
}
}
类图如下:
工厂模式在常用的日志logbock中也有体现,ILoggerFactory为工厂的抽象接口,下面有对应的实现工厂类
工厂方法适用于以下场景:
- 1、创建对象需要大量重复的代码。
- 2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
- 3、一个类通过其子类来指定创建哪个对象。
工厂方法也有缺点:
- 1、类的个数容易过多,增加复杂度。
- 2、增加了系统的抽象性和理解难度。
3.3 抽象工厂模式
抽象工厂模式(Abastract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现.
讲解抽象工厂之前,我们要了解两个概念产品等级结构和产品族,还是以手机和厂商为例,看下面的图:
从上图中看出有正方形,圆形和菱形三种图形,相同颜色的就代表同一个产品族,相同形状的代表同一个产品等级结构。同样可以从生活中来举例,比如,华为厂商生产多种电子设备。那么上图中,蓝色的圆形代表华为手机、蓝色的正方形就代表华为电脑、蓝色的菱形代表华为电视,蓝色一排都属于华为品牌,都是华为电子设备这个产品族。再看最右侧的菱形,蓝色的我们指定了代表华为电视,那么第二排翠绿色的菱形,代表苹果电视。
通过上面两张图的对比理解,相信大家对抽象工厂有了非常形象的理解。接下来我们来看一个具体的业务场景而且用代码来实现。还是以手机为例,一个工厂不单单只生产手机,还要生产电脑和电视。在产品等级中增加两个产品 ITv 电视和 IPc 电脑。
ITv接口:
package com.peng.abstarctfactory;
//电视产品接口
public interface ITv {
public void play();
}
IPc接口:
package com.peng.abstarctfactory;
public interface IPc {
public void play();
}
然后创建个抽象工厂AbstractFactory接口,可以看到该抽象工厂中定义了抽象产品族的规范
package com.peng.abstarctfactory;
import com.peng.IPhone;
public interface AbstractFactory {
//创建手机
public IPhone createPhone();
//创建电脑
public IPc createPc();
//创建电视
public ITv createTv();
}
拓展Huawei产品族的产品,分别创建HuaweiTv类以及HuaweiPc类
package com.peng.abstarctfactory;
public class HuaweiPc implements IPc{
@Override
public void play() {
System.out.println("华为电脑");
}
}
package com.peng.abstarctfactory;
public class HuaweiTv implements ITv{
@Override
public void play() {
System.out.println("华为电视");
}
}
创建Huawei产品族工厂,实现AbstractFactory接口
package com.peng.abstarctfactory;
import com.peng.HuaweiPhone;
import com.peng.IPhone;
public class HuaweiFactory implements AbstractFactory{
@Override
public IPhone createPhone() {
return new HuaweiPhone();
}
@Override
public IPc createPc() {
return new HuaweiPc();
}
@Override
public ITv createTv() {
return new HuaweiTv();
}
}
同样按照抽象工厂逻辑创建Apple产品族工厂类以及相应的Apple产品,这里不在展示。
客户端调用
package com.peng.abstarctfactory;
import com.peng.IPhone;
public class AbstarctFactoryTest {
public static void main(String[] args) {
//调用华为工厂
AbstractFactory abstractFactory = new HuaweiFactory();
IPhone huaweiPhone = abstractFactory.createPhone();
IPc huaweiPhonePc = abstractFactory.createPc();
ITv huaweiPhoneTv = abstractFactory.createTv();
//调用苹果工厂
AbstractFactory appleFactory = new AppleFactory();
IPhone applePhone = appleFactory.createPhone();
IPc applePc = appleFactory.createPc();
ITv appleTv = appleFactory.createTv();
}
}
上面的代码完整地描述了两个产品族 华为电子产品和 苹果电子产品,也描述了三个产品等级手机、电脑、电视。抽象工厂非常完美清晰地描述这样一层复杂的关系。类图如下:
但是,如果我们再继续扩展产品等级,将手表 Watch 也加入到电子产品中,那么我们的代码从抽象工厂,到具体工厂要全部调整,很显然不符合开闭原则。因此抽象工厂也是有缺点的:
- 1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
- 2、增加了系统的抽象性和理解难度。
3.4 抽象工厂的实际运用场景
这里我们举个实际项目中的例子,比如:一家保险经纪公司要对接多家保险公司实现保险产品的线上出单以及退保功能,这时如果多个产品并行开发,分配个不同的开发人员,为了防止代码的冲突,我们可以使用抽象工厂模式,将功能模块化,一个开发人员负责一家保险公司的对接。
我们引入三层架构的思想,建立Controller层,可以看到对外开放了两个接口,即出单和退保,通过传入的factoryName利用反射获取到相应的产品工厂,并且传入订单号告知要为哪笔订单做出单或者退保操作。
package com.peng.abstarctfactoryinsurance.controller;
import com.peng.abstarctfactoryinsurance.common.Result;
import com.peng.abstarctfactoryinsurance.dto.IssueDTO;
import com.peng.abstarctfactoryinsurance.dto.SurrenderDTO;
import com.peng.abstarctfactoryinsurance.factory.InsuranceFactoryService;
//对接保险公司Controller
public class InsuranceController {
@SuppressWarnings("deprecation")
public void issue(String factoryName,String orderNo) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
InsuranceFactoryService factoryService = (InsuranceFactoryService) Class.forName(factoryName).newInstance();
Result issueOrder = factoryService.issueOrder(new IssueDTO(orderNo));
System.out.println("出单调用结果:"+ issueOrder.getData());
}
public void surrender(String factoryName,String orderNo) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
InsuranceFactoryService factoryService = (InsuranceFactoryService) Class.forName(factoryName).newInstance();
Result surrenderOrder = factoryService.surrenderOrder(new SurrenderDTO(orderNo));
System.out.println("退保调用结果:"+ surrenderOrder.getData());
}
}
创建产品等级接口IIssue出单以及ISurrender退保
package com.peng.abstarctfactoryinsurance.product;
public interface IIssue {
//组装出单报文
public String buildIssueContent(String orderNo);
}
package com.peng.abstarctfactoryinsurance.product;
public interface ISurrender {
//组装退保报文
public String buildSurrenderContent(String orderNo);
}
创建产品等级的实现产品类,这里模拟两家保险公司
泰康保险产品类
package com.peng.abstarctfactoryinsurance.product;
public class TaikangIssue implements IIssue{
@Override
public String buildIssueContent(String orderNo) {
return "组装泰康出单报文成功" + orderNo;
}
}
package com.peng.abstarctfactoryinsurance.product;
public class TaikangSurrender implements ISurrender{
@Override
public String buildSurrenderContent(String orderNo) {
return "组装泰康退保报文成功" + orderNo;
}
}
阳光保险产品类
package com.peng.abstarctfactoryinsurance.product;
public class YangguangIssue implements IIssue{
@Override
public String buildIssueContent(String orderNo) {
return "组装阳光出单报文完成 "+ orderNo;
}
}
package com.peng.abstarctfactoryinsurance.product;
public class YangguangSurrender implements ISurrender{
@Override
public String buildSurrenderContent(String orderNo) {
return "组装阳光退保报文成功" + orderNo;
}
}
创建保险抽象工厂
package com.peng.abstarctfactoryinsurance.factory;
import com.peng.abstarctfactoryinsurance.common.Result;
import com.peng.abstarctfactoryinsurance.dto.IssueDTO;
import com.peng.abstarctfactoryinsurance.dto.SurrenderDTO;
public interface InsuranceFactoryService {
final static String CHARSET = "UTF-8";
//出单
public Result issueOrder(IssueDTO issueDTO);
//退保
public Result surrenderOrder(SurrenderDTO surrenderDTO);
}
创建泰康产品工厂
package com.peng.abstarctfactoryinsurance.factory;
import com.peng.abstarctfactoryinsurance.common.HttpClientUtil;
import com.peng.abstarctfactoryinsurance.common.Result;
import com.peng.abstarctfactoryinsurance.dto.IssueDTO;
import com.peng.abstarctfactoryinsurance.dto.SurrenderDTO;
import com.peng.abstarctfactoryinsurance.product.IIssue;
import com.peng.abstarctfactoryinsurance.product.ISurrender;
import com.peng.abstarctfactoryinsurance.product.TaikangIssue;
import com.peng.abstarctfactoryinsurance.product.TaikangSurrender;
public class TaiKangFactoryService implements InsuranceFactoryService{
@Override
public Result issueOrder(IssueDTO issueDTO) {
IIssue taikangIssue = new TaikangIssue();
//组装报文
String buildIssueContent = taikangIssue.buildIssueContent(issueDTO.getOrderNo());
//组装成功 使用http协议调用保险公司接口
String result = HttpClientUtil.doPost("http://taikang.com", buildIssueContent, CHARSET);
return new Result<String>(result);
}
@Override
public Result surrenderOrder(SurrenderDTO surrenderDTO) {
ISurrender taikangSurrender = new TaikangSurrender();
//组装报文
String buildSurrenderContent = taikangSurrender.buildSurrenderContent(surrenderDTO.getOrderNo());
//组装成功 使用http协议调用保险公司接口
String result = HttpClientUtil.doPost("http://taikang.com", buildSurrenderContent, CHARSET);
return new Result<String>(result);
}
}
创建阳光产品工厂
package com.peng.abstarctfactoryinsurance.factory;
import com.peng.abstarctfactoryinsurance.common.HttpClientUtil;
import com.peng.abstarctfactoryinsurance.common.Result;
import com.peng.abstarctfactoryinsurance.dto.IssueDTO;
import com.peng.abstarctfactoryinsurance.dto.SurrenderDTO;
import com.peng.abstarctfactoryinsurance.product.IIssue;
import com.peng.abstarctfactoryinsurance.product.ISurrender;
import com.peng.abstarctfactoryinsurance.product.YangguangIssue;
import com.peng.abstarctfactoryinsurance.product.YangguangSurrender;
public class YangguangFactoryService implements InsuranceFactoryService{
@Override
public Result issueOrder(IssueDTO issueDTO) {
IIssue yangguangIssue = new YangguangIssue();
//组装报文
String buildIssueContent = yangguangIssue.buildIssueContent(issueDTO.getOrderNo());
//组装成功 使用http协议调用保险公司接口
String result = HttpClientUtil.doPost("http://yangguang.com", buildIssueContent, CHARSET);
return new Result<String>(result);
}
@Override
public Result surrenderOrder(SurrenderDTO surrenderDTO) {
ISurrender yangguangSurrender = new YangguangSurrender();
//组装报文
String buildSurrenderContent = yangguangSurrender.buildSurrenderContent(surrenderDTO.getOrderNo());
//组装成功 使用http协议调用保险公司接口
String result = HttpClientUtil.doPost("http://yangguang.com", buildSurrenderContent, CHARSET);
return new Result<String>(result);
}
}
DTO传输层的类创建
package com.peng.abstarctfactoryinsurance.dto;
public class IssueDTO {
//订单号 用于出单
public String orderNo;
public IssueDTO(String orderNo) {
super();
this.orderNo = orderNo;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
}
package com.peng.abstarctfactoryinsurance.dto;
public class SurrenderDTO {
//订单号 用于退保
public String orderNo;
public SurrenderDTO(String orderNo) {
super();
this.orderNo = orderNo;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
}
公共组件类的创建,模拟httpClient
package com.peng.abstarctfactoryinsurance.common;
/*
* 利用HttpClient进行post请求的工具类
*/
public class HttpClientUtil {
public static String doPost(String url,String xmlContent,String charset){
System.out.println("请求地址 :" + url + "请求报文为:" + xmlContent);
return "返回结果";
}
}
创建统一的返参结果集
package com.peng.abstarctfactoryinsurance.common;
import java.io.Serializable;
/**
* 响应信息主体
*
* @param <T>
* @author Administrator
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
public static final int NO_LOGIN = -1;
public static final int SUCCESS = 200;
public static final int FAIL = 1;
public static final int NO_PERMISSION = 401;
private String msg = "success";
private int code = SUCCESS;
private T data;
public Result() {
super();
}
public Result(T data) {
super();
this.data = data;
}
public Result(T data, String msg) {
super();
this.data = data;
this.msg = msg;
}
public Result(Throwable e) {
super();
this.msg = e.getMessage();
this.code = FAIL;
}
public Result(int code,String msg){
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
最后调用测试
package com.peng.abstarctfactoryinsurance.test;
import com.peng.abstarctfactoryinsurance.controller.InsuranceController;
public class InsuranceTest {
public static void main(String[] args) {
//调用泰康出单
InsuranceController insuranceController = new InsuranceController();
try {
insuranceController.issue("com.peng.abstarctfactoryinsurance.factory.TaiKangFactoryService", "20190812212121");
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试结果:
请求地址 :http://taikang.com请求报文为:组装泰康出单报文成功20190812212121
出单调用结果:返回结果
通过上述代码,可以完美的解决对接多家保险公司时,代码冲突问题,相应的开发人员只会负责其相应的保险公司的对接,有很强的拓展性。 类图如下:
4 总结
通过工厂模式的学习,我们知道对于一些类进行抽象化,使其保持有很好的拓展性。但在实际应用中,我们千万不能犯强迫症甚至有洁癖。在实际需求中产品等级结构升级是非常正常的一件事情。我们可以根据实际情况,只要不是频繁升级,可以不遵循开闭原则。代码每半年升级一次或者每年升级一次又是符合常理的。