写点什么

GoF 设计模式 | 工厂方法模式

用户头像
Peision
关注
发布于: 2020 年 07 月 22 日
GoF设计模式 | 工厂方法模式

今天来学习23种设计模式的第二种,工厂方法模式,同时也是Java 中最常用的设计模式之一。

概念:



定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。



我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GOF 的 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”。



本文介绍的“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。



特点:



  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。

  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。



工厂方法的主要角色:



  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 new Product() 来创建产品。

  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。

  • 具体产品(Concrete Product):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。



类图分析:





核心代码:



  1. 图形的抽象类

package cn.ppdxzz.factorymethod.graph;
/**
* Description:图形抽象类
* @Author: PeiChen
*/
public abstract class Graph {
//开始绘制
public abstract void startDraw();
//结束绘制
public abstract void finishDraw();
}
  1. 图形的具体实现类(这里仅列举小万、小李绘制圆形的实现,重在这种设计思想的领悟)

package cn.ppdxzz.factorymethod.graph;
/**
* Description:小万绘制圆形
* @Author: PeiChen
*/
public class WanCircle extends Graph {
@Override
public void startDraw() {
System.out.println("小万开始绘制圆形...");
}
@Override
public void finishDraw() {
System.out.println("小万结束绘制圆形...");
System.out.println("-------------------");
}
}



package cn.ppdxzz.factorymethod.graph;
/**
* Description:小李绘制圆形
* @Author: PeiChen
*/
public class LiCircle extends Graph {
@Override
public void startDraw() {
System.out.println("小李开始绘制圆形...");
}
@Override
public void finishDraw() {
System.out.println("小李结束绘制圆形...");
System.out.println("-------------------");
}
}
  1. 将绘制图形的实例化功能抽象为抽象方法,在不同的绘制者的子类中具体实现。

package cn.ppdxzz.factorymethod.draw;
import cn.ppdxzz.factorymethod.graph.Graph;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Description:绘制图形的工厂类
* @Author: PeiChen
*/
public abstract class DrawGraph {
//定义一个绘图抽象方法,让各个工厂子类自己实现需要绘制什么图形
abstract Graph createGraph(String createType);
//构造方法
public DrawGraph() {
Graph graph = null;
String drawType;
do {
drawType = getType();
//抽象方法,由工厂子类完成图形的绘制
graph = createGraph(drawType);
if (graph != null) {
graph.startDraw();
graph.finishDraw();
}else {
System.out.println("图形输入有误,已退出!");
break;
}
}while (true);
}
//获取绘制者输入绘制的图形形状
private String getType() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入绘制的图形:");
try {
String str = reader.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
  1. 小万这个绘制者的具体实现类。

package cn.ppdxzz.factorymethod.draw;
import cn.ppdxzz.factorymethod.graph.Graph;
import cn.ppdxzz.factorymethod.graph.WanCircle;
import cn.ppdxzz.factorymethod.graph.WanRectangle;
import cn.ppdxzz.factorymethod.graph.WanTriangle;
/**
* Description:小万绘制的图形
* @Author: PeiChen
*/
public class DrawWanGraph extends DrawGraph {
@Override
Graph createGraph(String createType) {
Graph graph = null;
if ("circle".equals(createType)) {
graph = new WanCircle();
}else if ("rectangle".equals(createType)) {
graph = new WanRectangle();
}else if ("triangle".equals(createType)){
graph = new WanTriangle();
}
return graph;
}
}
  1. 小李这个绘制者的具体实现类。

package cn.ppdxzz.factorymethod.draw;
import cn.ppdxzz.factorymethod.graph.Graph;
import cn.ppdxzz.factorymethod.graph.LiCircle;
import cn.ppdxzz.factorymethod.graph.LiRectangle;
/**
* Description:小李绘制的图形
* @Author: PeiChen
*/
public class DrawLiGraph extends DrawGraph {
@Override
Graph createGraph(String createType) {
Graph graph = null;
if ("circle".equals(createType)) {
graph = new LiCircle();
}else if ("rectangle".equals(createType)){
graph = new LiRectangle();
}
return graph;
}
}
总结:



工厂方法模式非常符合“开闭原则”,当需要增加一个新的产品时,我们只需要增加一个具体的产品类和与之对应的具体工厂即可,无须修改原有系统。同时在工厂方法模式中用户只需要知道生产产品的具体工厂即可,无须关系产品的创建过程,甚至连具体的产品类名称都不需要知道。



虽然他很好的符合了“开闭原则”,但是由于每新增一个新产品时就需要增加两个类,这样势必会导致系统的复杂度增加。



工厂方法模式就讲解到这里,后面我们将会引入另一种设计模式——抽象工厂模式。

发布于: 2020 年 07 月 22 日阅读数: 55
用户头像

Peision

关注

除非我不想赢,否则没人能让我输! 2020.07.03 加入

还未添加个人简介

评论

发布
暂无评论
GoF设计模式 | 工厂方法模式