博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式——简单工厂模式
阅读量:7211 次
发布时间:2019-06-29

本文共 3790 字,大约阅读时间需要 12 分钟。

概述
简单工厂模式(Simple Factory Pattern)是通过专门定义一个工厂类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。它可以根据参数的不同返回不同类的实例,而无须知道其创建细节。如果在简单工厂模式中用于创建实例的方法是静态(static)方法,则被称为静态工厂方法(Static Factory Method)模式,它不属于23种设计模式,但在软件开发中应用也较为频繁,通常将它作为学习其他工厂模式的入门。其实工厂模式分为了最弱的简单工厂模式,工厂方法模式,牛逼的抽象工厂模式。
简单工厂模式结构中包括三种角色:
  • 工厂类(Factory):它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法,返回类型为抽象产品类型。
  • 抽象产品(Product):工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。
  • 具体产品(ConcreteProduct):简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。
实例应用
从我的一次面试经历说起,犹记得当年刚毕业时怀揣着要用代码拯救世界的梦想,结果现实是无情的,一次次求职碰壁,才发现自己图样图森破,唉,“满纸荒唐言,一把辛酸泪”,就把我的经历分享给初出茅庐的学弟们以做警戒吧,面试官给我出了个题目,要求利用一种面向对象的语言实现一个简单的计算器程序,我心想这不很简单吗,马上就把代码写出来,如下:
Scanner scanner=new Scanner(System.in);System.out.println("请输入第一个数");double numA=scanner.nextDouble();System.out.println("请输入第二个数");double numB=scanner.nextDouble();System.out.println("请输入运算符");String operate=scanner.next();double result=0;switch (operate){    case "+":        result=numA+numB;        break;    case "-":        result=numA-numB;        break;    case "*":        result=numA*numB;        break;    case "/":        result=numA/numB;        break;}System.out.println("最后结果为:"+result);
哈哈,自我感觉良好啊,然后面试官看了看,让我回去等消息,然后就没有然后了。。。多年后我才发现,当时是多么幼稚,看一下代码,先不说具体的异常处理问题,先说题目的要求——用一种面向对象的语言!我这写的完全是面向过程的代码。。。唉,都怨C语言学的太好了,呃~
很多面向对象编程的初学者都会有这样的问题,那就是遇到问题就直觉的用计算机的方式去思考,这样的思维虽然可以解决问题,但却使得我们的程序只满足当前的需求,程序不容易维护,不容易扩展,更不容易复用。既然认识到问题了,那我们就亡羊补牢吧,下面是我的修改版:
public double getResult(double numberA, double numberB, char operate) {    double result = 0d;    switch (operate) {        case '+':            result = numberA + numberB;            break;        case '-':            result = numberA - numberB;            break;        case '*':            result = numberA * numberB;            break;        case '/':            result = numberA / numberB;            break;        default:            break;    }    return result;}
代码功能都实现了,我将业务逻辑封装到了一个方法里,使用时直接调用即可,乍一看问题不大,仔细分析,发现还是有很多问题的
紧耦合vs松耦合
面向对象的三大特性:继承、多态、封装。我只用到了一个,倘若我现在要添加取余运算,怎么做?直接修改方法吗?如果一不小心把加号改成减号,那就惨了,这样的危险我们应该避免,所以最好的办法是把所有运算都分离出去,让他们之间相互不受影响,分析一下我们的代码,其实每种运算都涉及要运算的数和运算符,我们把他抽象出来,将共有特性进行抽象,这其实是为了更好的封装。
Operation运算类
public abstract class Operation {    public double numberA;    public double numberB;    public abstract double getResult();}

加减乘除类

public class OperationAdd extends Operation {    public double getResult() {        double result = 0d;        result = numberA + numberB;        return result;    }}public class OperationSub extends Operation {    public double getResult() {        double result = 0d;        result = numberA - numberB;        return result;    }}
剩下的几个运算类代码类似,就不写了
简单工厂类
public class OperationFactory {    public static Operation createOperate(char operate) {        Operation oper = null;        switch (operate) {            case '+':                oper = new OperationAdd();                break;            case '-':                oper = new OperationSub();                break;            case '*':                oper = new OperationMul();                break;            case '/':                oper = new OperationDiv();                break;            default:                break;        }        return oper;    }}
使用的时候,我们就可以这样使用
public static void main(String[] args) {    // TODO Auto-generated method stub    Operation oper;    oper= OperationFactory.createOperate('+');    oper.numberA=5;    oper.numberA=6;    double result=oper.getResult();}

看下程序的UML类图:

这样以来,各个运算类直接就没有关系了,我们修改某个类也不影响其他类运行,想要添加新的运算也只是添加运算子类和修改简单工厂类而已。
总结
简单工厂模式的主要优点如下:
  • 客户端可以免除直接创建对象的职责,只关心使用对象,简单工厂模式实现了对象创建和使用的分离。
  • 客户端不用知道创建产品类具体类名,只要知道具体产品类所对应的参数即可。
简单工厂模式的主要缺点如下:
  • 工厂类负责所有对象的创建逻辑,该类出问题整个系统挂掉。
  • 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑。
  • 简单工厂模式由于使用了静态工厂方法,所以工厂角色无法形成基于继承的等级结构。
参考:

你可能感兴趣的文章
Vert.x 发送邮件
查看>>
苹果文档 UISearchController的介绍
查看>>
iOS计步器实例
查看>>
vue国际化-vue-i18n的配置
查看>>
Java引用计数与实现
查看>>
Broadcast源码分析
查看>>
create-react-app 2.0中使用antd(eject)
查看>>
logstash常用插件介绍
查看>>
Git命令
查看>>
如何写出优质干净的代码,这6个技巧你不能错过!
查看>>
某口腔app发现了不友善词汇(f*ckMobile)
查看>>
SAP S/4HANA生产订单创建时使用的工厂数据是从什么地方带出来的
查看>>
JavaScript的数据类型有哪些?
查看>>
如何只在IE上加载CSS样式表
查看>>
个人博客三|首页后台开发
查看>>
调用链系列四:调用链上下文传递
查看>>
在Windows下,用Hexo搭建博客
查看>>
刷前端面经笔记(十一)
查看>>
【跃迁之路】【724天】程序员高效学习方法论探索系列(实验阶段481-2019.2.14)...
查看>>
Kaggle冠军经验分享丨如何用15个月冲到排行榜的首位
查看>>