当前位置: 首页 > 图灵资讯 > 技术篇> 23种设计模式——工厂方法模式

23种设计模式——工厂方法模式

来源:图灵教育
时间:2023-12-04 16:36:20

今天,我们将学习23种设计模式的第二种,工厂方法模式,Java 其中最常用的设计模式之一。

概念:

定义创建产品对象的工厂界面,将产品对象的实际创建推迟到特定的子工厂类别。这满足了创建模式所需的“创建与使用分离”的特点。

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

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

特点:
  • 使用者只需了解特定工厂的名称即可获得所需产品,无需了解产品的具体创建过程。
  • 当系统添加新产品时,只需添加特定的产品类别和相应的特定工厂类别,无需修改原工厂,以满足开关原则。
工厂方法的主要作用:
  • 抽象工厂(Abstract Factory):通过它,调用器提供了创建产品的界面,以访问特定工厂的工厂方法 new Product() 创造产品。
  • 具体工厂(Concrete Factory):主要是实现抽象工厂的抽象方法,创建具体产品。
  • 抽象产品(Product):对产品规范进行了定义,描述了产品的主要特点和功能。
  • 具体产品(Concrete Product):由具体工厂创建的抽象产品角色定义的接口,与具体工厂一一对应。
类图分析:

image.png

核心代码:
  1. 抽象类图形
package cn.ppdxzz.factorymethod.graph;/** * Description:图形抽象类 */public abstract class Graph {    //开始绘制    public abstract void startDraw();    //结束绘制    public abstract void finishDraw();}
  1. 图形的具体实现类别(这里只列出了小万和小李画圆的实现,重点是对这一设计理念的理解)
package cn.ppdxzz.factorymethod.graph;/** * Description:画圆形的小万 */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:小李画圆 */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:工厂类绘制图形 */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:小万画的图形 */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:小李画的图形 */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;    }}
总结:

工厂方法模式非常符合“开关原则”。当需要添加新产品时,我们只需要添加特定的产品类别和相应的特定工厂,而无需修改原始系统。同时,在工厂方法模式中,用户只需要知道产品的具体生产工厂可以,不需要关系产品的创建过程,甚至不需要知道具体的产品类别名称。

虽然他很好地遵循了“开关原则”,但每次添加新产品时都需要添加两个类别,这必然会增加系统的复杂性。

这里解释了工厂的方法模式,然后我们将引入另一种设计模式——抽象工厂模式。