热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java设计模式(二)——工厂模式

    当用户需要一个类的子类实例,且不希望与该类的子类形成耦合或者不知道该类

        当用户需要一个类的子类实例,且不希望与该类的子类形成耦合或者不知道该类有哪些子类可用时,可采用工厂模式;当用户需要系统提供多个对象,且希望和创建对象的类解耦时,可采用抽象工厂模式。

        工厂模式一般分为简单工厂、工厂、抽象工厂三种情况,属于创建型设计模式。

1. 关键角色

两个关键的角色:产品和工厂

两个角色的几种关系:

(1)单一产品系

高档中档低档
小汽车

(2)多产品系,特征相同

高档中档低档
小汽车
公共汽车

 (3)多产品系,部分特征相同

高档中档低档
小汽车
公共汽车

(4)多产品系,无特征相同

高档中档低档
小汽车
公共汽车

2. 简单工厂

简单工厂模式功能类编制步骤:

  • 定制抽象产品接口:ICar
  • 定制具体产品子类:UpCar MidCar DnCar
  • 定制工厂类:CarSimpleFactory

对于工厂类 create() 方法的理解:

         使用简单工厂的时候,通常不用创建简单工厂类的类实例,没有创建实例的必要,因此可以把简单工厂类实现成一个工具类,直接使用静态方法就可以了。也就是说,简单工厂的方法通常都是静态的,所以也被称为静态工厂。

(1)小汽车接口

public interface ICar {
}

(2)定义高、中、低档具体的汽车

public class UpCar implements ICar{
}

public class MidCar implements ICar{
}

public class DnCar implements ICar{
}

(3)简单工厂

public class CarSimpleFactory {public static final String UPTYPR = "uptype";public static final String MIDTYPR = "midtype";public static final String DNTYPR = "dntype";public static ICar create(String mark) {ICar obj = null;if (mark.equals(UPTYPR)) {obj = new UpCar();}else if (mark.equals(MIDTYPR)) {obj = new MidCar();}else if (mark.equals(DNTYPR)) {obj = new DnCar();}return obj;}
}

(4)测试

public class CarTest {public static void main(String[] args) {ICar obj = CarSimpleFactory.create("UPCAR");}
}

新的需求:

如果现在又新增加了一个超高档类型的汽车,在简单工厂模式下,需要做的工作有:

(1)新增ICar的子类SuperCar

(2)修改工厂类 SimpleCarFactory 中的create方法,增加SuperCar对象的判断选择分支。

能否不修改工厂类,就能完成所需功能呢?可以 使用工厂模式。

3. 工厂模式

工厂模式功能类编制步骤:

  • 定义抽象产品接口
  • 定义具体产品子类
  • 定义抽象工厂类  AbstractFactory,有一个重要的create抽象方法
  • 定义具体工厂子类

(1)定义小汽车接口

public interface ICar {
}

(2)定义高、中、低档具体的小汽车

public class UpCar implements ICar{
}public class MidCar implements ICar {
}public class DnCar implements ICar {
}

(3)定义抽象工厂

public abstract class AbstractFactory {public abstract ICar create();
}

(4)定义高档小汽车工厂

public class UpFactory extends AbstractFactory{@Overridepublic ICar create() {return new UpCar();}
}

(5)定义中档小汽车工厂

public class MidFactory extends AbstractFactory{@Overridepublic ICar create() {return new MidCar();}
}

(6)定义低档小汽车工厂

public class DnFactory extends AbstractFactory{@Overridepublic ICar create() {return new DnCar();}
}

(7)测试类

public class CarTest {public static void main(String[] args) {AbstractFactory obj = new UpFactory(); //多态创建高档工厂System.out.println(obj);ICar car = obj.create();}
}

工厂模式和简单工厂模式的区别:

  • 工厂模式把简单工厂中的具体工厂类划分成两层,抽象工厂层和具体工厂子类层。
  • create方法参数的理解,在简单工厂模式中,create(String mark) 是成员方法,表名在该方法中管理多个产品,根据mark的值产生并返回ICar对象;在工厂模式中,create是抽象方法,无参数,表名在具体的子类工厂中创建某个具体的产品。
  • 工厂方法更易于软件的二次开发和维护,主要特征是:当需求分析发生变化时,只需要增加、删除相应的类,而不是修改已有的类。

例如,又生产了一种超高档的小汽车,只需要增加SuperCar及SuperFactory两个类即可:

public class SuperCar implements ICar{
}

public class SuperFactory extends AbstractFactory{@Overridepublic ICar create() {return new SuperCar();}
}

4. 抽象工厂

        一般来说,简单工厂、工厂模式是单产品系的,而抽象工厂是多产品系得。从本质上讲,抽象工厂、工厂模式是统一得。

抽象工厂模式功能类编制步骤如下:

  • 定制抽象产品接口 如 ICar IBus
  • 定制具体产品子类  如 UpCar MidCar DnCar UpBus MidBus
  • 定制抽象工厂类   如 AbstractFactory 有两个create方法,分别返回ICar 和 IBus对象
  • 定制具体工厂子类

(1) 定义小汽车接口

public interface ICar {
}

定义高、中、低档小汽车

public class UpCar implements ICar {
}public class MidCar implements ICar {
}public class DnCar implements ICar {
}

(2)定义公共汽车接口

public interface IBus {
}

定义高、中、低档公共汽车

public class UpBus implements IBus{
}public class MidBus implements IBus{
}public class DnBus implements IBus{
}

(3)定义抽象工厂

public abstract class AbstractFactory {public abstract ICar createCar();public abstract IBus createBus();
}

(4)定义高档、中档、低档工厂

public class UpFactory extends AbstractFactory{@Overridepublic ICar createCar() {return new UpCar();}@Overridepublic IBus createBus() {return new UpBus();}
}

public class MidFactory extends AbstractFactory{@Overridepublic ICar createCar() {return new MidCar();}@Overridepublic IBus createBus() {return new MidBus();}
}

public class DnFactory extends AbstractFactory{@Overridepublic ICar createCar() {return new DnCar();}@Overridepublic IBus createBus() {return new DnBus();}
}

在Spring Boot框架中并不是哪里都使用了工厂模式,但是工厂模式确实被广泛地应用在Spring Boot中的一些关键组件中。以下是一些常见的使用工厂模式的Spring Boot组件:

  1. BeanFactory和ApplicationContext接口:Spring Boot中的BeanFactory和ApplicationContext接口都是使用工厂模式的典型例子。它们充当了对象工厂的角色,负责创建和管理Bean实例。

  2. RestTemplate类:RestTemplate类是一个非常流行的Spring Boot组件,它用于发送HTTP请求。RestTemplate使用工厂方法模式创建HTTP请求工厂实例,以便根据请求类型和其他配置创建合适的请求实例。

  3. JdbcTemplate类:JdbcTemplate类是一个用于执行SQL查询和更新的Spring Boot组件。它使用工厂方法模式创建数据源和JDBC连接实例。

  4. DispatcherServlet类:DispatcherServlet类是Spring Boot中的核心组件之一,用于处理HTTP请求和响应。它使用工厂方法模式创建HandlerMapping和HandlerAdapter实例,以便将请求路由到正确的处理程序方法并执行请求。

总之,Spring Boot框架中的许多组件都使用了工厂模式来创建和管理对象。这些组件可以更好地实现松耦合和可维护性,使得应用程序更加灵活和可扩展。

对于BeanFactory:

BeanFactory 是 Spring 框架中的一个关键接口,它使用工厂模式来创建和管理 Bean 实例。在 Spring Boot 中,BeanFactory 是 ApplicationContext 接口的父接口,也就是 ApplicationContext 继承了 BeanFactory 接口,因此 ApplicationContext 也是一个工厂模式的实现。

在使用 Spring Boot 框架时,我们通常会通过配置文件(比如 XML 配置文件、Java 配置类等)来定义 Bean,然后通过 BeanFactory 来获取 Bean 的实例。BeanFactory 的实现类可以根据配置文件中定义的信息创建对应的 Bean 实例,而且还可以对 Bean 的生命周期进行管理。

在 Spring Boot 中,我们通常使用如下方式来获取 BeanFactory 的实例:

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;public class MyBeanFactoryExample {public static void main(String[] args) {// 通过 ClassPathResource 加载配置文件ClassPathResource resource = new ClassPathResource("applicationContext.xml");// 创建 XmlBeanFactory 实例BeanFactory factory = new XmlBeanFactory(resource);// 通过 BeanFactory 获取指定名称的 Bean 实例MyBean myBean = (MyBean)factory.getBean("myBean");myBean.sayHello();}
}

在上面的代码中,我们首先使用 ClassPathResource 类加载了一个名为 applicationContext.xml 的配置文件,然后创建了一个 XmlBeanFactory 实例,最后通过 getBean() 方法获取了一个名为 myBean 的 Bean 实例,并调用了它的 sayHello() 方法。

总的来说,BeanFactory 接口是 Spring 框架中最基本的工厂模式实现,它用于创建和管理 Bean 实例,而且非常灵活、可扩展。如果需要更高级的功能(比如自动注入、AOP 等),可以使用 ApplicationContext 接口,它是 BeanFactory 接口的扩展,同时也是一个更加高级的工厂模式实现。


推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
author-avatar
手机用户2702933824
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有