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程序设计有所帮助。

相关文章

  • Seata AT模式如何实现行锁详解

    Seata AT模式如何实现行锁详解

    这篇文章主要为大家介绍了Seata AT模式如何实现行锁详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • PowerJob的UserService工作流程源码解读

    PowerJob的UserService工作流程源码解读

    这篇文章主要介绍了PowerJob的UserService工作流程源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • 阿里云发布 Spring Boot 新脚手架工程

    阿里云发布 Spring Boot 新脚手架工程

    这篇文章主要介绍了阿里云发布 Spring Boot 新脚手架的相关资料,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,可以参考下
    2020-04-04
  • java kafka写入数据到HDFS问题

    java kafka写入数据到HDFS问题

    这篇文章主要介绍了java kafka写入数据到HDFS问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • 通过代码实例了解SpringBoot启动原理

    通过代码实例了解SpringBoot启动原理

    这篇文章主要介绍了通过代码实例了解SpringBoot启动原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java 如何实现AES加密

    Java 如何实现AES加密

    这篇文章主要介绍了Java 如何实现AES加密,帮助大家完成对接,完成自身需求,感兴趣的朋友可以了解下
    2020-10-10
  • Maven的pom.xml中resources标签的用法

    Maven的pom.xml中resources标签的用法

    本文主要介绍了Maven的pom.xml中resources标签的用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Java实现获取客户端真实IP方法小结

    Java实现获取客户端真实IP方法小结

    本文给大家汇总介绍了2种使用java实现获取客户端真实IP的方法,主要用于获取使用了代理访问的来访者的IP,有需要的小伙伴可以参考下。
    2016-03-03
  • java线程中断 interrupt 和 LockSupport解析

    java线程中断 interrupt 和 LockSupport解析

    这篇文章主要为大家介绍了java线程中断 interrupt 和 LockSupport示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • Java如何实现图片的叠加与拼接操作

    Java如何实现图片的叠加与拼接操作

    这篇文章主要介绍了Java如何实现图片的叠加与拼接操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11

最新评论