设计模式之工厂方法模式(Java实现)

举报
长路 发表于 2022/11/28 18:04:14 2022/11/28
【摘要】 文章目录前言一、认识工厂模式二、引出工厂模式三、工厂模式实现3.1、简单工厂模式3.2、工厂方法模式总结参考资料 前言 本篇博客是关于工厂方法模式的实现,若文章中出现相关问题,请指出! 对应代码地址:Gitee(demo-exer/ java-Lear23designpatterns)、Github(java-demo/ java-Lear23designpatterns) 所有博客文件目录索引:

@[toc]

前言

本篇博客是关于工厂方法模式的实现,若文章中出现相关问题,请指出!

对应代码地址:Gitee(demo-exer/ java-Lear23designpatterns)Github(java-demo/ java-Lear23designpatterns)

所有博客文件目录索引:博客目录索引(持续更新)


一、认识工厂模式

工厂模式定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂中,实现了创建者与调用者的分离!

工厂模式分类简单工厂模式工厂方法模式抽象工厂模式

  • 简单工厂模式:将被创建的对象称为"产品",把创建产品的对象称为"工厂",若是产品不多,可通过使用一个工厂类即可完成,若是出现新的产品,需要去修改原有的方法,这违法了开闭原则。由于在简单工厂中创建对象的方法是static,所以又被称为静态工厂模式。该模式并不算在GoF23种设计模式之中。
    • 应用场景:Spring中的BeanFactory
  • 工厂方法模式:解决了简单工厂模式违反开闭原则,在工厂方法模式中每一个产品都对应着一个工厂类,满足了开闭原则,就是需要付出更多的代价,若是产品特别多那么整体代码量会巨大。
    • 应用场景:SpringMybatis的结合(FactoryBean接口)。
  • 抽象工厂模式:围绕一个超级工厂来创建其他工厂,该超级工厂又称为其他工厂的工厂。


二、引出工厂模式

我们通常去创建一个对象的实例需要通过自己去手动new来创建实例,这种方式又称为无工厂模式,对于一些较复杂且需要多项配置时就比较头疼了,需要一个个填入到构造器中,造成不必要的麻烦!

下面代码就通过手动new的方式来获取实例:

interface Car {
    void name();
}

//宝马
class BMW implements Car{
    @Override
    public void name() {
        System.out.println("宝马");
    }
}

//保时捷
class Porsche implements Car{
    @Override
    public void name() {
        System.out.println("保时捷");
    }
}

//消费者
public class Customer {

    public static void main(String[] args) {
        //通过手动new的方式来获取产品实例
        Car bmw = new BMW();
        Car porsche = new Porsche();
        bmw.name();
        porsche.name();
    }
}

image-20210315205121544

在日常开发中,凡是需要生成复杂对象的地方,都可以尝试考虑使用工厂模式来代替!



三、工厂模式实现

3.1、简单工厂模式

简单工厂模式:由于工厂的方法是static所以也叫做静态工厂模式。简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式。(但该模式并不在GoF23种设计模式中)

好处

  1. 相对于无工厂模式,我们不再通过new来获取自己想要创建的实例,而是通过一个工厂类方法,只需要传入指定的参数就能够获取到我们想要的对象实例。
  2. 使用工厂方法时无需只要知道执行的类名,只需要知道能够创建实例的参数即可。

缺点

  1. 一旦新增产品,我们就需要回到原有的工厂类创建实例方法中进行修改,否则无法扩展其他产品,这违反开闭原则(扩展功能,不要修改原来的方法)。
  2. 简单工厂模式工厂类单一,负责所有产品的创建,职责过重一旦出现异常整个系统都会受到影响,若是产品量过多,工厂类创建实例方法会非常臃肿。违法了单一职责原则

应用场景

  • 对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。

简单工厂模式实现

image-20210315213358224

interface Car {
    void name();
}

//宝马
class BMW implements Car{
    @Override
    public void name() {
        System.out.println("宝马");
    }
}

//保时捷
class Porsche implements Car{
    @Override
    public void name() {
        System.out.println("保时捷");
    }
}

public class CarFactory {
    
    //传入指定名称来获取具体产品实例
    public static Car getCar(String name){
        if("宝马".equals(name)){
            return new BMW();
        }else if("保时捷".equals(name)){
            return new Porsche();
        }
        return null;
    }
}


public class Main {
    public static void main(String[] args){
        //通过工厂类来创建指定产品实例
        Car bmw = CarFactory.getCar("宝马");
        Car porsche = CarFactory.getCar("保时捷");
        bmw.name();
        porsche.name();
    }
}
  • 添加了一个汽车工厂类CarFactory,其中添加一个创建产品方法getCar()根据传入参数来创建实例。
  • 其中工厂创建方法通过if..else来判断创建也可以使用switch.case.进行创建。

image-20210315211048180

说明:在简单工厂模式中,若是增加了其他产品则需要回到原来的方法中进行修改操作,这就违背了开闭原则,之后通过工厂方法模式则能够遵守该规则。不过有一说一,对于这种简单工厂模式在实际应用中会大量使用。



3.2、工厂方法模式

工厂方法模式:是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则,但是需要付出一定代价(对于产品很多并且零件很多情况下,造成创建工厂类过多情况)。

优点

  1. 用户只需要知道具体工厂的名称即可得到所需要的产品,无需知道产品创建的过程。
  2. 更具有灵活性,当新增产品时,我们只需要创建一个相对应的工厂类,满足开闭原则
  3. 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则依赖倒置原则里氏替换原则

缺点

  1. 若是产品类过多,那么也就意味着创建对应数量的产品工厂,增加了复杂度。
  2. 增加了系统的抽象性和理解程度。

工厂方法模式实现

在工厂方法模式中,我们添加一个工厂接口,一个产品对应一个工厂类,该工厂类实现该接口,顾客则通过指定产品的工厂类方法来获取产品实例,可见下图:

image-20210315214604537

通过使用一个接口来规范工厂的获取实例方法:

interface Car {
    void name();
}

//宝马
class BMW implements Car{
    @Override
    public void name() {
        System.out.println("宝马");
    }
}

//保时捷
class Porsche implements Car{
    @Override
    public void name() {
        System.out.println("保时捷");
    }
}

//新增一个工厂接口
interface Factory{
    Car getCar();
}

public class BMWFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new BMW();
    }
}

public class PorscheFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new Porsche();
    }
}


public class Main {
    public static void main(String[] args){
        //通过对应产品的工厂类来获取实例
        Car bmw = new BMWFactory().getCar();
        Car porsche = new PorscheFactory().getCar();
        bmw.name();
        porsche.name();
    }
}

image-20210315215811294

看一下多个接口及类的UML图:

image-20210315232622877

我们能够看到结构变得更加清晰了,想要哪个汽车类型即可从对应类型的工厂中拿到,但是随着产品的增多,工厂类也会增多,增加了复杂度。



总结

简单工厂模式(静态工厂模式):其并不属于GoF23种设计模式的范畴中,并在某种程度上并不符合设计原则,但实际使用最多。

工厂方法模式:符合开闭原则,当添加新的产品时不需要更改原有的方法代码,直接通过增加新的工厂类实现扩展。

这两种模式都是针对于某个产品!



参考资料

[1]. C语言中文网—简单工厂模式

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。