设计模式——简单工厂模式

简介: 概述简单工厂模式(Simple Factory Pattern)是通过专门定义一个工厂类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
概述
简单工厂模式(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类图:


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

相关文章
|
1月前
|
设计模式 SQL 算法
设计模式了解哪些,模版模式
设计模式了解哪些,模版模式
22 0
|
2月前
|
设计模式 Java uml
C++设计模式之 依赖注入模式探索
C++设计模式之 依赖注入模式探索
56 0
|
3月前
|
设计模式 前端开发 JavaScript
观察者模式 vs 发布-订阅模式:两种设计模式的对决!
欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚开始学习前端的读者们打造的。无论你是初学者还是有一些基础的开发者,我们都会在这里为你提供一个系统而又亲切的学习平台。我们以问答形式更新,为大家呈现精选的前端知识点和最佳实践。通过深入浅出的解释概念,并提供实际案例和练习,让你逐步建立起一个扎实的基础。无论是HTML、CSS、JavaScript还是最新的前端框架和工具,我们都将为你提供丰富的内容和实用技巧,帮助你更好地理解并运用前端开发中的各种技术。
|
1月前
|
设计模式 Java 数据库
小谈设计模式(2)—简单工厂模式
小谈设计模式(2)—简单工厂模式
|
10天前
|
设计模式 前端开发 Java
19:Web开发模式与MVC设计模式-Java Web
19:Web开发模式与MVC设计模式-Java Web
20 4
|
15天前
|
设计模式 消息中间件 Java
Java 设计模式:探索发布-订阅模式的原理与应用
【4月更文挑战第27天】发布-订阅模式是一种消息传递范式,被广泛用于构建松散耦合的系统。在 Java 中,这种模式允许多个对象监听和响应感兴趣的事件。
35 2
|
18天前
|
设计模式 存储 JavaScript
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
|
18天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
|
20天前
|
设计模式
设计模式(一)简单工厂模式
设计模式(一)简单工厂模式
14 0
|
1月前
|
设计模式 Java
小谈设计模式(9)—工厂方法模式
小谈设计模式(9)—工厂方法模式