一.定义
定义一个创建对象的的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行
二.适用场景
- 创建对象需要大量重复的代码
- 客户端不依赖于产品类实例如何被创建、实现等细节
- 一个类(接口)通过其子类来指定创建哪个对象
三.角色
- 产品接口: 所有产品的父类,负责描述产品的公共接口
- 产品实现类: 具体产品实体
- 工厂接口: 所有工厂的父类,负责描述工厂的公共接口
- 具体产品的工厂实现类: 生产具体产品的工厂
- 调用端(客户端): 调用生产产品的方法
四.优缺点
1.优点
- 用户只需要关心所需产品对应的工厂,无须关心创建细节
- 加入新产品符合开闭原则,提高可扩展性
2.缺点
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
五.实例
1.一个产品抽象(产品接口)
/**
* 抽象电脑类
* @author shixinke
*/
public interface Computer {
/**
* 获取电脑的名称(型号)
* @return
*/
String getName();
/**
* 获取操作系统名称
* @return
*/
String getOsName();
}
2.一个工厂抽象(工厂接口)
/**
* 电脑工厂
* @author shixinke
*/
public interface ComputerFactory {
/**
* 生产电脑
* @return
*/
Computer produce();
}
3.具体产品实现类
(1)具体产品实现类1
/**
* Dell电脑
* @author shixinke
*/
public class DellComputer implements Computer {
public String getName() {
return "dell电脑";
}
public String getOsName() {
return "windows 10";
}
}
(2)具体产品实现类2
/**
* mac电脑
* @author shixinke
*/
public class MacComputer implements Computer {
public String getName() {
return "mac电脑";
}
public String getOsName() {
return "Mac OS";
}
}
(3)具体产品实现类3
public class ThinkPadComputer implements Computer {
public String getName() {
return "ThinkPad 4700";
}
public String getOsName() {
return "windows 10";
}
}
4.具体的工厂类
(1)具体的工厂实现类1
/**
* Dell电脑工厂
* @author shixinke
*/
public class DellComputerFactory implements ComputerFactory {
public Computer produce() {
return new DellComputer();
}
}
(2)具体的工厂实现类2
/**
* mac电脑工厂
* @author shixinke
*/
public class MacComputerFactory implements ComputerFactory {
public Computer produce() {
return new MacComputer();
}
}
(3)具体的工厂实现类3
/**
* ThinkPad电脑工厂
* @author shixinke
*/
public class ThinkPadComputerFactory implements ComputerFactory {
public Computer produce() {
return new ThinkPadComputer();
}
}
5.客户端(调用端)
/**
* 电脑测试类
* @author shixinke
*/
public class ComputerTest {
public static void main(String[] args) {
/**
* 创建一个Dell工厂,那它生产的就是Dell电脑
*/
ComputerFactory factory = new DellComputerFactory();
/**
* 因为是Dell工厂,因此生产的产品就是Dell电脑
*/
Computer computer = factory.produce();
System.out.println(computer.getName());
}
}
以上类的UML关系图:
六.工厂方法在源码中的使用
1.工厂方法在JDK中的应用
(1)Collection中的iterator方法
- 抽象产品
public interface Iterator<E> {
boolean hasNext();
E next();
}
- 抽象工厂
Iterator<E> iterator();
- 具体产品
ArrayList中的Itr
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
}
- 具体的工厂
ArrayList
其UML图如下:
2.工厂方法在logback中的使用
- 抽象工厂
package org.slf4j;
public interface ILoggerFactory {
Logger getLogger(String var1);
}
- 抽象产品
package org.slf4j;
public interface Logger {
}
- 具体工厂实现
package ch.qos.logback.classic;
public class LoggerContext extends ContextBase implements ILoggerFactory, LifeCycle {
}
- 具体产品
package ch.qos.logback.classic;
public final class Logger implements org.slf4j.Logger, LocationAwareLogger, AppenderAttachable<ILoggingEvent>, Serializable {
}
其UML图如下: