软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。
也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。
其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。
那么我们今天来看看设计模式中的第二种工厂模式中的工厂方法模式。
在现实生活中社会分工越来越细,越来越专业化,各种产品有专门的工厂生产,彻底告别了自给自足的小农经济时代,这大大缩短了产品的生产周期,提高了生产效率。那么我们可能会考虑在软件开发中能否做到软件对象的生产和使用相分离呢?而这便需要我们的设计模式中的工厂模式。
首先我们来回想一下,社会由最开始的自给自足原始社会,到农耕小作坊时代,到工业革命流水线,再到现代产业链代工厂,我们会发现生产的效率越来越高,其实整个社会的进步就是工厂模式发展的缩影。最开始自给自足是没有工厂;到小作坊简单完成商品的生产,为简单工厂模式;到工业革命流水线,商品完成自产自销,为工厂方法模式;到现阶段产业链代工厂,如现在的富士康等企业,为其他企业提供工厂流水线,为抽象工厂模式。
什么是工厂模式呢?
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。所有我们在实际开发中,凡是需要生成复杂对象的地方,都可以尝试考虑使用工厂模式来代替。而按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。
所以紧接着我们来依次根据不同的场景看看这几种工厂模式。
我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫**“简单工厂模式”**。
在简单工厂模式中创建实例的方法通常为静态(static)方法
因此简单工厂模式(Simple Factory Pattern)又叫作静态工厂方法模式(Static Factory Method Pattern)。
首先我们来看看简单工厂模式的组成:
绘制结构图如下:
图-1 简单工厂模式结构图
如果我们用 java 代码表示是怎样的呢?
/** * @author hz * @version 1.0 */public class Client { //抽象产品 public interface Product { void show(); } //具体产品:ProductA static class ConcreteProduct1 implements Product { public void show() { System.out.println("具体产品1显示..."); } } //具体产品:ProductB static class ConcreteProduct2 implements Product { public void show() { System.out.println("具体产品2显示..."); } } final class Const { static final int PRODUCT_A = 0; static final int PRODUCT_B = 1; static final int PRODUCT_C = 2; } static class SimpleFactory { public static Product makeProduct(int kind) { switch (kind) { case Const.PRODUCT_A: return new ConcreteProduct1(); case Const.PRODUCT_B: return new ConcreteProduct2(); } return null; } }}
复制代码
该模式的优缺点有哪些呢?
优点:
缺点:
但是简单工厂模式每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度,违背了**“开闭原则”**,因此我们进行进一步对简单工厂进行抽象,这个也是我们后面马上将给大家说的工厂模式的第二个实现场景,工厂方法模式。
前面我们说了简单工厂模式违背了开闭原则,而“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
工厂方法模式的主要角色包含:
绘制结构图如下:
对比简单工厂模式,工厂方法模式在之间简单的工厂的基础之上将工厂进行拆分成抽象工厂和具体工厂两部分内容,这样灵活性得到大量提升。
而这种模式我们可以在那些场合使用呢?
如果我们用 java 代码表示是怎样的呢?
/** * @author hz * @version 1.0 */public class AbstractFactoryTest { public static void main(String[] args) { try { Product a; AbstractFactory af; af = (AbstractFactory) ReadXML.getObject(); //抽象工厂内容放入到外部配置文件xml/properties等文件中,通过I/O流加载从而创建出抽象工厂 a = af.newProduct(); a.show(); } catch (Exception e) { System.out.println(e.getMessage()); } }}//抽象产品:提供了产品的接口interface Product { public void show();}//具体产品1:实现抽象产品中的抽象方法class ConcreteProduct1 implements Product { public void show() { System.out.println("具体产品1显示..."); }}//具体产品2:实现抽象产品中的抽象方法class ConcreteProduct2 implements Product { public void show() { System.out.println("具体产品2显示..."); }}//抽象工厂:提供了厂品的生成方法interface AbstractFactory { public Product newProduct();}//具体工厂1:实现了厂品的生成方法class ConcreteFactory1 implements AbstractFactory { public Product newProduct() { System.out.println("具体工厂1生成-->具体产品1..."); return new ConcreteProduct1(); }}//具体工厂2:实现了厂品的生成方法class ConcreteFactory2 implements AbstractFactory { public Product newProduct() { System.out.println("具体工厂2生成-->具体产品2..."); return new ConcreteProduct2(); }}
复制代码
import javax.xml.parsers.*;import org.w3c.dom.*;import java.io.*;/** * @author hz * @version 1.0 */public class ReadXML { //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象 public static Object getObject() { try { //创建文档对象 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("src/FactoryMethod/config1.xml")); //获取包含类名的文本节点 NodeList nl = doc.getElementsByTagName("className"); Node classNode = nl.item(0).getFirstChild(); String cName = "FactoryMethod." + classNode.getNodeValue(); //System.out.println("新类名:"+cName); //通过类名生成实例对象并将其返回 Class<?> c = Class.forName(cName); Object obj = c.newInstance(); return obj; } catch (Exception e) { e.printStackTrace(); return null; } }
}
复制代码
那么该模式有哪些优缺点呢?
优点:
缺点:
对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。
对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来,那么我们可以采用工厂方法模式,如 JAVA 中的 Colletion 中的 iterator() 方法;
或者我们只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的,我们也可以选用工厂方法模式。
但是注意当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类。这时工厂方法模式将退化到简单工厂模式。
不管是简单工厂模式还是我们的工厂方法模式考虑的都是一系列相同类型的产品,如果生产的产品类型不是一个类型,那我们怎么处理呢,这就需要我们的工厂模式的另一种模式-抽象工厂模式。
领取专属 10元无门槛券
私享最新 技术干货