说明
工厂模式总共分为3种,1.简单工厂模式(Simple Factory Pattern) 2.工厂方法(Factory Method Pattern) 3.抽象工厂模式(Abstract Factory Pattern),这篇文章会展示3种不同的工厂模式的差异和写法。
定义
- 定义:定义一个创建对象接口
但让视线这个接口的类来决定实例化哪个类
工厂方法让类的实例化推迟到子类中进行 - 类型:创建型
适用场景
- 创建对象需要大量重复代码
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 一个类通过其子类来制指定创建哪个对象
优点
- 用户只需要关系产品对应的工厂,无需关心创建细节
- 加入新产品符合开闭原则,提高可扩展性
缺点
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
工厂模式中的角色
简单工厂角色说明
- Product(产品)
- Product角色属于框架房,是一个抽象类,是对创建类的一个具体抽象。
- ConcreteProduct(实际的产品)
- ConcreteCreator角色属于具体的实际加工方,它是实际工厂创建的实际产品。
- ConcreteCreator(实际的创建者)
- ConcreteCreator角色属于实际加工方,它负责生产实际的产品。
简单工厂类图
工厂方法角色说明
- Product(产品)
- Product角色属于框架房,是一个抽象类,是对创建类的一个具体抽象。
- Creator(创建者)
- Creator角色属于框架房,它是负责生成Product角色的抽象类,但具体的处理是由子类ConcreteCreator角色决定。
- ConcreteProduct(实际的产品)
- ConcreteCreator角色属于具体的实际加工方,它是实际工厂创建的实际产品。
- ConcreteCreator(实际的创建者)
- ConcreteCreator角色属于实际加工方,它负责生产实际的产品。
工厂方法类图
抽象工厂角色说明
- AbstractProduct(抽象产品)
AbstractProduct
角色负责定义AbstractFactory
角色所生成的抽象零件和产品接口。
- AbstractFactory(抽象工厂)
AbstractFactory
角色负责定义用于生成抽象产品的接口。
- ConcreteProduct(实际产品)
ConcreteProduct
角色负责实现AbstractProduct
角色的接口。
- ConcreteFactory(实际工厂)
ConcreteFactory
角色负责实现AbstractFactory
角色的接口。
抽象工厂类图
代码实现
1. 简单工厂模式写法一
第一步,写一个Book
接口,对应角色中Product
public interface Book {
/**
* 读书
*/
void read();
}
第二步,写Book
的实现类JavaBook
,对应角色中ConcreteProduct
public class GoBook implements Book{
@Override
public void read() {
System.out.println("写一本Go从入门到精通");
}
}
第三步,再写一个Book
的实现类PythonBook
public class GoBook implements Book{
@Override
public void read() {
System.out.println("写一本Go从入门到精通");
}
}
第四步,写简单工厂类
public class BookFactory {
private final String javaBook = "java";
private final String goBook = "go";
public Book createBook(String name) {
if (javaBook.equalsIgnoreCase(name)) {
return new JavaBook();
}else if (goBook.equalsIgnoreCase(name)){
return new GoBook();
}else {
return null;
}
}
}
最后,写简单工厂测试类
public class SimpleFactoryTest {
public static void main(String[] args) {
BookFactory bookFactory = new BookFactory();
Book javaBook = bookFactory.createBook("java");
javaBook.read();
}
}
1.1 简单工厂模式执行结果
执行简单工厂测试结果
2. 简单工厂写法二
简单工厂写法一在增加Book
的时候,每次都需要根据产品的增加修改代码逻辑,不符合开闭原则,因此可以使用反射来优化,优化代码前三步都是相同,知识在工厂方法实现方式上不同,我们直接跳到第四步工厂方法的实现
public class BookFactory {
public Book createBook(String className) {
try {
if (className != null && className.length() > 0) {
return (Book) Class.forName(className).newInstance();
}
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
第五步,简单工厂写法二测试实现类相同
public class SimpleFactoryTest {
public static void main(String[] args) {
BookFactory bookFactory = new BookFactory();
Book javaBook = bookFactory.createBook(JavaBook.class.getName());
javaBook.read();
}
}
2.1 简单工厂写法二执行结果
可以看到简单工厂写法二执行结果和写法一相同,但写法二符合开闭原则。
3. 工厂方法
工厂方法模式的写法中前三步与简单工厂模式中相同,这里就不重复赘述了,那我们从第四步开始写。
第四步,声明一个BookFactory
接口,就是角色中的Creator
public interface BookFactory {
Book create();
}
第五步,实现一个JavaBookFacotory
,也就是角色中的ConcreteCreator
public class JavaBookFactory implements BookFactory {
@Override
public Book create() {
return new JavaBook();
}
}
第六步,再实现一个GoBookFactory
public class GoBookFactory implements BookFactory {
@Override
public Book create() {
return new GoBook();
}
}
第七步,完成工厂方法测试类
public class FactoryMethodTest {
public static void main(String[] args) {
BookFactory javaBookFactory = new JavaBookFactory();
Book javaBook = javaBookFactory.create();
javaBook.read();
System.out.println("\n"+"==========我是分割线========="+"\n");
BookFactory goBookFactory = new GoBookFactory();
Book goBook = goBookFactory.create();
goBook.read();
}
}
3.1 工厂方法模式执行结果
4. 抽象工厂模式
举个例子,我们读一本书,会将学习到的知识记录成笔记,但是我们的笔记可能包含好几个部分,比如书上的笔记(BookNote),笔记本上记录的笔记(Note)以及电脑中的学习笔记(ENote)。
第一步,先创建BookNote
,Note
和ENote
接口或抽象类,在类图中是AbstractProduct
角色。
public interface ENote {
void typing();
}
public interface BookNote {
void mark();
}
public interface Note {
void write();
}
第二步,分别创建三者实现类,在类图中是ConcreteProduct
角色。
public class JavaBookNote implements BookNote{
@Override
public void mark() {
System.out.println("在Java从入门到精通上标注了一段话!");
}
}
public class JavaENote implements ENote{
@Override
public void typing() {
System.out.println("在电脑上敲了一段java笔记");
}
}
public class JavaNote implements Note {
@Override
public void write() {
System.out.println("在笔记本上写了一段java笔记");
}
}
public class GoBookNote implements BookNote{
@Override
public void mark() {
System.out.println("在Go从入门到精通上标注了一段话!");
}
}
public class GoENote implements ENote{
@Override
public void typing() {
System.out.println("在电脑上敲了一段go笔记");
}
}
public class GoNote implements Note {
@Override
public void write() {
System.out.println("在笔记本上写了一段Go笔记");
}
}
第三步,创建抽象工厂接口/抽象类,在类图中是AbstractFactory
角色。
public interface NoteFactory {
/**
* 创建图书笔记
* @return
*/
BookNote createBookNote();
/**
* 创建电子笔记
* @return
*/
ENote createENote();
/**
* 创建笔记本笔记
* @return
*/
Note createNote();
}
第四步,创建抽象工厂实现类,在类图中是ConcreteFactory
角色。
public class JavaNoteFactory implements NoteFactory{
@Override
public BookNote createBookNote() {
return new JavaBookNote();
}
@Override
public ENote createENote() {
return new JavaENote();
}
@Override
public Note createNote() {
return new JavaNote();
}
}
public class GoNoteFactory implements NoteFactory{
@Override
public BookNote createBookNote() {
return new GoBookNote();
}
@Override
public ENote createENote() {
return new GoENote();
}
@Override
public Note createNote() {
return new GoNote();
}
}
第五步,创建抽象工厂测试类
public class AbstractFactoryTest {
public static void main(String[] args) {
NoteFactory javaNoteFactory = new JavaNoteFactory();
BookNote javaBookNote = javaNoteFactory.createBookNote();
ENote javaENote = javaNoteFactory.createENote();
Note javaNote = javaNoteFactory.createNote();
javaBookNote.mark();
javaENote.typing();
javaNote.write();
System.out.println("\n"+"==========我是分割线========="+"\n");
NoteFactory goNoteFactory = new GoNoteFactory();
BookNote goBookNote = goNoteFactory.createBookNote();
ENote goENote = goNoteFactory.createENote();
Note goNote = goNoteFactory.createNote();
goBookNote.mark();
goENote.typing();
goNote.write();
}
}