Java设计模式之工厂模式分析【简单工厂、工厂方法、抽象工厂】

 更新时间:2018年04月26日 10:50:30   作者:aronykl  
这篇文章主要介绍了Java设计模式之工厂模式,结合实例形式分析了简单工厂、工厂方法、抽象工厂等相关功能、实现与使用方法,需要的朋友可以参考下

本文实例讲述了Java设计模式之工厂模式。分享给大家供大家参考,具体如下:

一、 简单工厂

先来思考一个问题。我们平时写程序时,会有这种情况,A对象里面需要调用B对象的方法,这时我们使用的一般是new关键字来创建一个B实例,然后调用B实例的方法。这种做法的坏处在于:A类的方法实现直接调用了B类的类名(这种方式也被称为硬编码耦合),一旦系统需要重构:需要使用C类来代替B类时,程序就不得不修改A类代码,如果应用中有100个或者10000个类以硬编码方式耦合了B类,则需要修改100个、10000个地方,这显然是一种非常可怕的事情。

换一个角度来看这个问题:对已A对象而言,它只需要调用B对象的方法,并不关心B对象的实现、创建过程,考虑让B类实现一个IB接口,而A类只需要与IB接口耦合——A类并不直接使用new关键字来创建B实例,而是重新定义一个工厂类:IBFactory,由该工厂类负责创建IB实例,而A类用过调用IBFactory工厂的方法来得到IB的实例。通过以上设计:需要使用C类代替B类,则只需要让C类也实现IB接口,并改写IBFactory工厂中创建IB实例的实现代码,让该工厂产生C实例即可。这种将多个类对象交给工厂类来生成的设计方式叫做简单工厂模式。

以下是简单工厂模式的代码:

/**
 * 简单工厂模式
 *
 * 需要工厂生产的对象实例所实现的共同的接口
 * 发型接口
 * @author Administrator
 *
 */
public interface Hair {
  /**
   * 画发型
   */
  public void draw();
}
/**
 * 左偏分发型
 * @author Administrator
 *
 */
public class LeftHair implements Hair {
  @Override
  public void draw() {
    System.out.println("----------------画左偏分发型-----------------");
  }
}
/**
 * 右偏分发型
 * @author Administrator
 *
 */
public class RightHair implements Hair {
  @Override
  public void draw() {
    System.out.println("-----------------画右偏分发型------------------");
  }
}
/**
 * 生产发型的工厂
 * 要生产什么发型 只需在这里改就行了
 * @author Administrator
 *
 */
public class HairFactory {
  public Hair getHair() {
    return new LeftHair();
    //return new RightHair();
  }
}
/**
 * 客户端测试类
 * @author Administrator
 *
 */
public class HairTest {
  public static void main(String[] args) {
    HairFactory factory = new HairFactory();
    Hair hair = factory.getHair();
    hair.draw();
  }
}

可以看到,如果想把HairTest里面生成的LeftHair改成RightHair,只需修改HairFactory里面getHair方法的实现即可。

使用简单工厂模式的优势在于:让对象的调用者和对象的创建过程分离,当对象调用者需要对象时,直接向工厂请求即可,从而避免了对象的调用者与对象实现类以硬编码方式耦合,以提高系统的可维护性、可扩展性。当然,工厂模式也有一个小小的缺陷,当产品修改时,工厂类也要做相应的修改,此处可使用策略模式进行解决,下面是代码。

public interface HairBuilder {
  /**
   * 制造发型
   * @return
   */
  public Hair getHair();
}
public class LeftHairBuilder implements HairBuilder {
  @Override
  public Hair getHair() {
    return new LeftHair();
  }
}
public class RightHairBuilder implements HairBuilder {
  @Override
  public Hair getHair() {
    return new RightHair();
  }
}
public class HairFactory {
  private HairBuilder hairBuilder;
  public HairFactory(HairBuilder hairBuilder) {
    this.hairBuilder = hairBuilder;
  }
  public void setHairBuilder(HairBuilder hairBuilder) {
    this.hairBuilder = hairBuilder;
  }
  public Hair getHair() {
    return hairBuilder.getHair();
  }
}
public class HairTest {
  public static void main(String[] args) {
//   HairBuilder builder = new LeftHairBuilder();
    HairBuilder builder = new RightHairBuilder();
    HairFactory factory = new HairFactory(builder);
    Hair hair = factory.getHair();
    hair.draw();
  }
}

这种做法的好处是无需再去修改工厂类,将工厂里面的创建对量逻辑根据不同的策略抽象出来,程序需要创建什么对象,只需网工厂中传入相应的builder即可。

二、工厂方法

在简单工厂模式中,系统使用工厂类生产所有产品实例,且该工厂类决定生产哪个类的实例,即工厂类负责所有的逻辑判断、实例创建等工作。

如果不想再工厂类中进行逻辑判断,程序可以为不同的产品类提供不同的工厂,不同的工厂类生产不同的产品,无需再工厂类中进行复杂的逻辑判断。这就有点类似于上面的简单工厂模式结合策略模式,不同的是前者只有一个工厂,后者需要有多个工厂。下面是工厂方法模式的代码。

/**
 * 工厂方法模式
 * 需要工厂生产的对象实例所实现的共同的接口
 * @author Administrator
 *
 */
public interface Person {
  public void drawPerson();
}
public class Man implements Person {
  @Override
  public void drawPerson() {
    System.out.println("---------------------draw a man--------------------");
  }
}
public class Women implements Person {
  @Override
  public void drawPerson() {
    System.out.println("--------------------draw a women---------------------");
  }
}
/**
 * 生产人的工厂
 * @author Administrator
 *
 */
public interface PersonFactory {
  //生产人
  public Person getPerson();
}
/**
 * 生产man的工厂
 * @author Administrator
 *
 */
public class ManFactory implements PersonFactory {
  @Override
  public Person getPerson() {
    return new Man();
  }
}
/**
 * 声场women的工厂
 * @author Administrator
 *
 */
public class WomenFactory implements PersonFactory {
  @Override
  public Person getPerson() {
    return new Women();
  }
}
/**
 * 客户端测试类
 * @author Administrator
 *
 */
public class PersonTest {
  public static void main(String[] args) {
//   PersonFactory factory = new ManFactory();
    PersonFactory factory = new WomenFactory();
    Person person = factory.getPerson();
    person.drawPerson();
  }
}

这种的典型的特点就是在客户端代码中根据不同的工厂生产其对应的产品,不必把复杂的逻辑都放在工厂类里面判断。这种实现有一个很明显的缺陷,就是客户端与工厂类进行了耦合。

三、抽象工厂

采用上面的工厂方法的设计架构,客户端代码成功与被调用对象的实现类分离,但带来了另一种耦合:客户端代码与不同的工厂类耦合。为了解决这种耦合的问题,考虑在增加一个工厂类,用来生成工厂实例,实现生产产品的工厂与客户端分离,这种设计方式被称为抽象工厂模式。下面是抽象工厂模式的代码

/**
 * 抽象工厂模式
 * 生产PersonFactory的工厂
 * @author Administrator
 *
 */
public class PersonFactoryFactory {
  public static PersonFactory getPersonFactory(String type) {
    if(type.equalsIgnoreCase("man")) {
      return new ManFactory();
    } else {
      return new WomenFactory();
    }
  }
}
/**
 * 客户端测试类
 * @author Administrator
 *
 */
public class PersonTest {
  public static void main(String[] args) {
    PersonFactory factory = PersonFactoryFactory.getPersonFactory("man");
    Person person = factory.getPerson();
    person.drawPerson();
  }
}

更多java相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • springboot 自定义属性与加载@value示例详解

    springboot 自定义属性与加载@value示例详解

    在SpringBoot框架中,自定义属性通常通过application.properties文件配置,并使用@Value注解加载,虽然这是一种可行的方法,但存在一种更优雅的实现方式,本文给大家介绍springboot 自定义属性与加载@value的相关操作,感兴趣的朋友一起看看吧
    2024-10-10
  • java 中链表的定义与使用方法

    java 中链表的定义与使用方法

    这篇文章主要介绍了java 中链表的定义与使用方法的相关资料,需要的朋友可以参考下
    2017-03-03
  • 深入理解Java之jvm启动流程

    深入理解Java之jvm启动流程

    这篇文章主要介绍了深入理解Java之jvm启动流程,文章内容讲解的很清晰,有对这方面感兴趣的同学可以研究下
    2021-02-02
  • MyBatis中#{}和${}有哪些区别

    MyBatis中#{}和${}有哪些区别

    大家好,本篇文章主要讲的是MyBatis中#{}和${}区别,感兴趣的同学赶快来看一看,对你有帮助的话记得收藏一下,方向下次浏览
    2021-12-12
  • Spring事务原理解析

    Spring事务原理解析

    Spring事务有可能会提交,回滚、挂起、恢复,所以Spring事务提供了一种机制,可以让程序员来监听当前Spring事务所处于的状态,这篇文章主要介绍了Spring底层事务原理,需要的朋友可以参考下
    2022-12-12
  • 详解SpringBoot注入数据的方式

    详解SpringBoot注入数据的方式

    这篇文章主要介绍了详解SpringBoot注入数据的方式,详细的介绍了几种注入方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • eclipse连接不到genymotion问题的解决方案

    eclipse连接不到genymotion问题的解决方案

    今天小编就为大家分享一篇关于eclipse连接不到genymotion问题的解决方案,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Java利用过滤器实现完善登录功能

    Java利用过滤器实现完善登录功能

    这篇文章主要为大家详细介绍了Java如何利用过滤器实现完善登录功能,文中的示例代码讲解详细,对我们学习Java有一定帮助,需要的可以参考一下
    2022-09-09
  • 浅析Java迭代器Iterator和Iterable的区别

    浅析Java迭代器Iterator和Iterable的区别

    Java语言中,Iterator和Iterable都是用来遍历集合类数据结构的接口,虽然它们有很多相似的地方,但在具体实现中却有着一些不同之处,本文将详细分析它们的区别,并提供相应的代码示例,需要的朋友可以参考下
    2023-07-07
  • Kotlin 泛型详解及简单实例

    Kotlin 泛型详解及简单实例

    这篇文章主要介绍了 Kotlin 泛型详解及简单实例的相关资料,需要的朋友可以参考下
    2017-06-06

最新评论