JAVA设计模式之创建者模式中的三种工厂模式

工厂模式归属于设计模式中的创建者模式,其主要用途是为了让我们更加优雅的创建JAVA对象,常见的工厂模式主要分为简单工厂、工厂方法、抽象方法三种形式,具体使用中并不拘泥于形式。

所属分类 JAVA

相关标签 工厂设计模式

前言

我们在实际写代码过程中往往不会过度强调在用哪种设计模式。

但了解学习优秀的设计模式能够便于我们写出更为优质的代码。

采用设计模式编写代码可以具备易用、拓展、清晰等多种特质。

既便如此,在实际编写过程中,不能被设计模式所束缚,因地制宜才是最好的。

本文主要讲述的是,创建者模式中的工厂模式。

模式介绍

创建者模式:为了用更加优雅的方式创建对象。

工厂模式:字如其意,用于创建对象的中心,主要为了生产出需要的对象。

该模式使用的频次较少,简单来说就是你需要什么,我创建什么。

该设计模式主要为了将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。

简单工厂方法是静态方法,可通过工厂类类名直接调用,只需要传入一个简单的参数即可,无须知道对象的创建细节。

可以将参数保存在XML等格式的配置文件中,修改时无须修改任何Java源代码。

但是,工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则。

//产品接口
interface Person{
    void create();
}
//产品实现类
public class Man implements Person {
    @Override
    public String create() {
        return "Create Man";
    }
}
public class Woman implements Person {
    @Override
    public String create() {
        return "Create Woman";
    }
}
//工厂类
public class PersonFactory {
    public static Person create(String what)
    {
        Person person = null;
        switch (what)
        {
            case "M" :
                person = new Man();
                break;
            case "W" :
                person = new Woman();
                break;
        }
        return person;
    }
}
//最终调用
Person man = PersonFactory.create("M");
Person woman = PersonFactory.create("W");

优点:

  • 实现了对象创建和使用的分离
  • 一定程度上提高了系统的灵活性,对象使用者无需知晓创建对象的细节

缺点:

  • 工厂类集中了所有产品的创建逻辑,过度依赖工厂类,实际上提高了代码耦合度
  • 增加了系统的复杂度和理解难度
  • 系统扩展困难,添加新产品不得不修改工厂逻辑,重构频次过高
  • 使用静态工厂方法,工厂无法基于继承的等级结构,不能得到很好地扩展

场景:

  • 少类型的对象创建,不会造成工厂方法中的业务逻辑太过复杂
  • 使用者不想过多关心对象创建细节,想快速达成对象创建

工厂方法模式(Factory Method Pattern)简称工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式。

工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

工厂方法模式是简单工厂模式的进一步抽象和推广,保持了简单工厂模式的优点,并克服了它的缺点。

核心工厂类不再负责所有产品的创建,而是将具体创建工作交给其子类去完成,允许系统在不修改工厂角色的情况下引进新产品。

实际过程为:增加具体产品-->增加具体工厂,符合开闭原则。

//产品接口
interface Person{
    void create();
}
//产品实现类
public class Man implements Person {
    @Override
    public String create() {
        return "Create Man";
    }
}
//以上与简单工厂一致
//工厂方法父类(接口类)
interface PersonFactory {
    Person createPerson();
}
//工厂方法子类(实现类)
public class ManFactory implements PersonFactory {
    @Override
    public Person createPerson() {
        return new Man();
    }
}
//实际调用
PersonFactory manFactory = new ManFactory();
Person man = manFactory.createPerson();

优点:

  • 工厂方法用来创建客户所需要的产品,隐藏了哪种具体产品类将被实例化的细节
  • 自主选择需要使用的子类工厂,创建对象的细节封装在具体工厂内部
  • 在系统中加入新产品时,增加对应的子类(实现)工厂

缺点:

  • 一定程度上增加了系统的复杂度,会给系统带来一些额外的开销,增加了对应工厂类
  • 增加了系统的抽象性和理解难度

场景:

  • 使用者只需要知道所对应的工厂即可创建对象
  • 较多的细分产品类适用于工厂方法创建

抽象工厂模式(Abstract Factory Pattern),提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类,抽象工厂模式又称为Kit模式。

抽象工厂模式中存在着产品族和产品等级两大概念。

产品族:同一个工厂生产的,位于不同产品等级结构中的一组产品,如下方代码的女人、女孩

产品等级:产品等级结构即产品的继承结构,如下方代码的女性->女人,女性->女孩

//产品族 男性
public interface Male {
}
//男性产品等级下男人
public class Man implements Male {
}
//男性产品等级下男孩
public class Boy implements Male {
}
//同理女性产品族
public interface Female {
}
public class Woman implements Female {
}
public class Girl implements Female {
}
//抽象工厂
interface PersonFactory {
    public Male createMale();
    public Female createFemale();
}
//实现工厂 成年生产工厂
public class AdultFactory implements PersonFactory {
    @Override
    public Male createMale() {
        return new Man();
    }
    @Override
    public Female createFemale() {
        return new Woman();
    }
}
//实现工厂 幼年生产工厂
public class ChildFactroy implements PersonFactory {
    @Override
    public Male createMale() {
        return new Boy();
    }
    @Override
    public Female createFemale() {
        return new Girl();
    }
}
//最终调用
PersonFactory adultFactory = new AdultFactory();
Male man = adultFactory.createMale();
Female woman = adultFactory.createFemale();
PersonFactory childFactory = new ChildFactroy();
Male boy = childFactory.createMale();
Female girl = childFactory.createFemale();

优点:

  • 使用者无需知晓具体对象的生成
  • 产品族中的多个对象被设计成一起工作时,能够保证使用者只使用同一个产品族中的对象
  • 增加新的产品族很方便,无须修改已有系统,符合开闭原则

缺点:

  • 当增加新的产品等级,需大改,甚至修改抽象层代码,重构成本高,违背了开闭原则

场景:

  • 系统不依赖于产品类实例如何被创建、组合和表达的细节
  • 系统中有多于一个的产品族,每次只使用其中某一产品族
  • 属于同一个产品族的产品将在一起使用时
  • 产品等级结构稳定,在设计完成之后不会向系统中增加新的产品等级结构或者删除已有的产品等级结构

备注

实际编写代码并不会局限于使用某一种设计模式。

代码在不断优化升级重构过程中会出现模式的迁移情况。

无论采用何种设计模式,编码时我们要考虑这些特质:

  • 逻辑清晰,模块划分合理
  • 可读性高
  • 健壮性高
  • 灵活,易扩展和易迁移。

米虫

做一个有理想的米虫,伪全栈程序猿,乐观主义者,坚信一切都是最好的安排!

本站由个人原创、收集或整理,如涉及侵权请联系删除

本站内容支持转发,希望贵方携带转载信息和原文链接

本站具有时效性,不提供有效、可用和准确等相关保证

本站不提供免费技术支持,暂不推荐您使用案例商业化

发表观点

提示

昵称

邮箱

QQ

网址

当前还没有观点发布,欢迎您留下足迹!

同类其他

JAVA

listener、filter、servlet的加载次序

在web.xml中经常会看到listener,filter,servlet的相关标签配置,它们分别是监听器、过滤器、容器,都是在项目启动的时候就可以进行初始化的加载动作

JAVA中创建线程的三种方式的使用与区别

JAVA中通过继承Thread类、实现Runnable接口以及实现Callable接口配合Future接口实现创建多线程,三种方式各有优缺点,而第三种则具备更多的增强能力

SpringBoot配置文件生效优先级

SpringBoot 可以通过 spring.profiles.active 属性指定生效不同配置文件来满足多环境要求,多环境更为复杂的场景,就需要理解配置文件生效优先级,考虑直接引入外部配置项和配置文件

自定义filter过滤器拦截未登录(非法)请求

在JAVA的WEB工程中我们可以将JSP页面文件放在WEB-INFO中限制用户进行URL直接访问,但静态资源如js、css文件却是需要被外部直接访问的,直接对外暴露又不太安全,可以通过自定义过滤器处理

Maven的pom配置文件的scope属性

scope属性主要用于控制依赖范围,主要分为编译、打包、运行、测试、依赖传递等各个常见,scope不同于optional提供了更多可选择的配置参数用于应对不同的依赖场景。

JAVA语言中的反射机制的作用原理及使用

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;动态获取的信息以及动态调用对象的方法的功能。

选择个人头像

昵称

邮箱

QQ

网址

评论提示

  • 头像:系统为您提供了12个头像自由选择,初次打开随机为你选择一个
  • 邮箱:可选提交邮箱,该信息不会外泄,或将上线管理员回复邮件通知
  • 网址:可选提交网址,评论区该地址将以外链的形式展示在您的昵称上
  • 记忆:浏览器将记忆您已选择或填写过得信息,下次评论无需重复输入
  • 审核:提供一个和谐友善的评论环境,本站所有评论需要经过人工审核