设计模式之(二):工厂方法设计模式

工厂方法模式内容概览

一.定义

定义一个创建对象的的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行

二.适用场景

  • 创建对象需要大量重复的代码
  • 客户端不依赖于产品类实例如何被创建、实现等细节
  • 一个类(接口)通过其子类来指定创建哪个对象

三.角色

  • 产品接口: 所有产品的父类,负责描述产品的公共接口
  • 产品实现类: 具体产品实体
  • 工厂接口: 所有工厂的父类,负责描述工厂的公共接口
  • 具体产品的工厂实现类: 生产具体产品的工厂
  • 调用端(客户端): 调用生产产品的方法

四.优缺点

1.优点
  • 用户只需要关心所需产品对应的工厂,无须关心创建细节
  • 加入新产品符合开闭原则,提高可扩展性
2.缺点
  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度

五.实例

1.一个产品抽象(产品接口)
  1. /**
  2. * 抽象电脑类
  3. * @author shixinke
  4. */
  5. public interface Computer {
  6. /**
  7. * 获取电脑的名称(型号)
  8. * @return
  9. */
  10. String getName();
  11. /**
  12. * 获取操作系统名称
  13. * @return
  14. */
  15. String getOsName();
  16. }
2.一个工厂抽象(工厂接口)
  1. /**
  2. * 电脑工厂
  3. * @author shixinke
  4. */
  5. public interface ComputerFactory {
  6. /**
  7. * 生产电脑
  8. * @return
  9. */
  10. Computer produce();
  11. }
3.具体产品实现类
(1)具体产品实现类1
  1. /**
  2. * Dell电脑
  3. * @author shixinke
  4. */
  5. public class DellComputer implements Computer {
  6. public String getName() {
  7. return "dell电脑";
  8. }
  9. public String getOsName() {
  10. return "windows 10";
  11. }
  12. }
(2)具体产品实现类2
  1. /**
  2. * mac电脑
  3. * @author shixinke
  4. */
  5. public class MacComputer implements Computer {
  6. public String getName() {
  7. return "mac电脑";
  8. }
  9. public String getOsName() {
  10. return "Mac OS";
  11. }
  12. }
(3)具体产品实现类3
  1. public class ThinkPadComputer implements Computer {
  2. public String getName() {
  3. return "ThinkPad 4700";
  4. }
  5. public String getOsName() {
  6. return "windows 10";
  7. }
  8. }
4.具体的工厂类
(1)具体的工厂实现类1
  1. /**
  2. * Dell电脑工厂
  3. * @author shixinke
  4. */
  5. public class DellComputerFactory implements ComputerFactory {
  6. public Computer produce() {
  7. return new DellComputer();
  8. }
  9. }
(2)具体的工厂实现类2
  1. /**
  2. * mac电脑工厂
  3. * @author shixinke
  4. */
  5. public class MacComputerFactory implements ComputerFactory {
  6. public Computer produce() {
  7. return new MacComputer();
  8. }
  9. }
(3)具体的工厂实现类3
  1. /**
  2. * ThinkPad电脑工厂
  3. * @author shixinke
  4. */
  5. public class ThinkPadComputerFactory implements ComputerFactory {
  6. public Computer produce() {
  7. return new ThinkPadComputer();
  8. }
  9. }
5.客户端(调用端)
  1. /**
  2. * 电脑测试类
  3. * @author shixinke
  4. */
  5. public class ComputerTest {
  6. public static void main(String[] args) {
  7. /**
  8. * 创建一个Dell工厂,那它生产的就是Dell电脑
  9. */
  10. ComputerFactory factory = new DellComputerFactory();
  11. /**
  12. * 因为是Dell工厂,因此生产的产品就是Dell电脑
  13. */
  14. Computer computer = factory.produce();
  15. System.out.println(computer.getName());
  16. }
  17. }

以上类的UML关系图:

工厂方法模式

六.工厂方法在源码中的使用

1.工厂方法在JDK中的应用
(1)Collection中的iterator方法
  • 抽象产品
  1. public interface Iterator<E> {
  2. boolean hasNext();
  3. E next();
  4. }
  • 抽象工厂
  1. Iterator<E> iterator();
  • 具体产品

ArrayList中的Itr

  1. private class Itr implements Iterator<E> {
  2. int cursor; // index of next element to return
  3. int lastRet = -1; // index of last element returned; -1 if no such
  4. int expectedModCount = modCount;
  5. }
  • 具体的工厂
  1. ArrayList

其UML图如下:

Iterator类图

2.工厂方法在logback中的使用
  • 抽象工厂
  1. package org.slf4j;
  2. public interface ILoggerFactory {
  3. Logger getLogger(String var1);
  4. }
  • 抽象产品
  1. package org.slf4j;
  2. public interface Logger {
  3. }
  • 具体工厂实现
  1. package ch.qos.logback.classic;
  2. public class LoggerContext extends ContextBase implements ILoggerFactory, LifeCycle {
  3. }
  • 具体产品
  1. package ch.qos.logback.classic;
  2. public final class Logger implements org.slf4j.Logger, LocationAwareLogger, AppenderAttachable<ILoggingEvent>, Serializable {
  3. }

其UML图如下:

Logger类图