博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式——简单工厂模式
阅读量:7174 次
发布时间: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类图:

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

你可能感兴趣的文章
51la图片做网店流量统计
查看>>
压力测试工具JMeter入门教程
查看>>
MySQL 百万级分页优化 数据库优化
查看>>
np.concatenate 拼接
查看>>
PHP编译错误解决:Don't know how to define struct flock on this system, set --enable-opcache=no...
查看>>
Linux命令(6):more命令
查看>>
HTTPD配置文件MPM(非7.0以上版本)
查看>>
Upgrade GI/CRS 11.1.0.7 to 11.2.0.2. Rootupgrade.sh Hanging
查看>>
nginx的高级配置(5)——访问控制
查看>>
DG_Oracle DataGuard Switchover主备节点切换(案例)
查看>>
CentOS7系统常用命令
查看>>
10.2.0.1 db console启动失败问题一例
查看>>
linux下查看文件编码及修改编码
查看>>
VC中的延时
查看>>
算法与数据结构知识点
查看>>
在单位成功实验的PIX配置
查看>>
centos6.x使用dd命令制作u盘启动
查看>>
如何使用Wireshark抓包
查看>>
mysql 时间函数用法 集合
查看>>
技术宅男既要提升编程技术也要加强沟通能力
查看>>