共计 5047 个字符,预计需要花费 13 分钟才能阅读完成。
软件设计模式(Software Design Pattern),又称 设计模式,是一套被重复应用、少数人通晓的、通过分类编目标、代码设计教训的总结。它形容了在软件设计过程中的一些一直反复产生的问题,以及该问题的解决方案。
也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计教训的总结,具备肯定的普遍性,能够重复应用。
其目标是为了进步代码的可重用性、代码的可读性和代码的可靠性。
那么咱们明天来看看设计模式中的第二种工厂模式中的 工厂办法模式。
在现实生活中社会分工越来越细,越来越专业化,各种产品有专门的工厂生产,彻底辞别了自力更生的小农经济时代,这大大缩短了产品的生产周期,进步了生产效率。那么咱们可能会思考在软件开发中是否做到软件对象的生产和应用相拆散呢?而这便须要咱们的设计模式中的 工厂模式。
首先咱们来回忆一下,社会由最开始的自力更生原始社会,到农耕小作坊时代,到工业革命流水线,再到古代产业链代工厂,咱们会发现生产的效率越来越高,其实整个社会的提高就是工厂模式倒退的缩影。最开始自力更生是没有工厂;到小作坊简略实现商品的生产,为简略工厂模式;到工业革命流水线,商品实现自产自销,为工厂办法模式;到现阶段产业链代工厂,如当初的富士康等企业,为其余企业提供工厂流水线,为 形象工厂模式。
什么是工厂模式呢?
定义一个创立产品对象的工厂接口,将产品对象的理论创立工作推延到具体子工厂类当中。这满足创立型模式中所要求的“创立与应用相拆散”的特点。所有咱们在理论开发中,但凡须要生成简单对象的中央,都能够尝试思考应用工厂模式来代替。而按理论业务场景划分,工厂模式有 3 种不同的实现形式,别离是简略工厂模式、工厂办法模式和形象工厂模式。
所以紧接着咱们来顺次依据不同的场景看看这几种工厂模式。
简略工厂模式
咱们把被创立的对象称为“产品”,把创立产品的对象称为“工厂”。如果要创立的产品不多,只有一个工厂类就能够实现,这种模式叫“简略工厂模式”。
在简略工厂模式中创立实例的办法通常为 动态(static)办法
因而简略工厂模式(Simple Factory Pattern)又叫作 动态工厂办法模式(Static Factory Method Pattern)。
首先咱们来看看简略工厂模式的组成:
- 简略工厂(SimpleFactory):是简略工厂模式的外围,负责实现创立所有实例的外部逻辑。工厂类的创立产品类的办法能够被外界间接调用,创立所需的产品对象。
- 形象产品(Product):是简略工厂创立的所有对象的父类,负责形容所有实例共有的公共接口。
- 具体产品(ConcreteProduct):是简略工厂模式的创立指标。
绘制结构图如下:
图 -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;
}
}
}
该模式的优缺点有哪些呢?
长处:
- 工厂类蕴含必要的逻辑判断,能够决定在什么时候创立哪一个产品的实例。客户端能够罢黜间接创立产品对象的职责,很不便的创立出相应的产品。工厂和产品的职责辨别明确。
- 客户端无需晓得所创立具体产品的类名,只需晓得参数即可。
- 也能够引入配置文件,在不批改客户端代码的状况下更换和增加新的具体产品类。
毛病:
- 简略工厂模式的工厂类繁多,负责所有产品的创立,职责过重,一旦异样,整个零碎将受影响。且工厂类代码会十分臃肿,违反高聚合准则。
- 应用简略工厂模式会减少零碎中类的个数(引入新的工厂类),减少零碎的复杂度和了解难度
- 零碎扩大艰难,一旦减少新产品不得不批改工厂逻辑,在产品类型较多时,可能造成逻辑过于简单
- 简略工厂模式应用了 static 工厂办法,造成工厂角色无奈造成基于继承的等级构造。
然而简略工厂模式每减少一个产品就要减少一个具体产品类和一个对应的具体工厂类,这减少了零碎的复杂度,违反了“开闭准则”,因而咱们进行进一步对简略工厂进行形象,这个也是咱们前面马上将给大家说的工厂模式的第二个实现场景,工厂办法模式。
工厂办法模式
后面咱们说了简略工厂模式违反了开闭准则,而“工厂办法模式”是对简略工厂模式的进一步抽象化,其益处是能够使零碎在不批改原来代码的状况下引进新的产品,即满足开闭准则。
工厂办法模式的次要角色蕴含:
- 形象工厂(Abstract Factory):提供了创立产品的接口,调用者通过它拜访具体工厂的工厂办法 newProduct() 来创立产品。
- 具体工厂(ConcreteFactory):次要是实现形象工厂中的形象办法,实现具体产品的创立。
- 形象产品(Product):定义了产品的标准,形容了产品的次要个性和性能。
- 具体产品(ConcreteProduct):实现了形象产品角色所定义的接口,由具体工厂来创立,它同具体工厂之间一一对应。
绘制结构图如下:
图 -2 工厂办法模式
比照简略工厂模式,工厂办法模式在之间简略的工厂的根底之上将工厂进行拆分成形象工厂和具体工厂两局部内容,这样灵活性失去大量晋升。
而这种模式咱们能够在那些场合应用呢?
- 用户只须要晓得具体工厂的名称就可失去所要的产品,毋庸晓得产品的具体创立过程。
- 灵活性加强,对于新产品的创立,只需多写一个相应的工厂类。
- 典型的解耦框架。高层模块只须要晓得产品的抽象类,毋庸关怀其余实现类,满足迪米特法令、依赖倒置准则和里氏替换准则。
如果咱们用 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() 办法;
或者咱们只是须要一种产品,而不想晓得也不须要晓得到底是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们依据以后零碎的状况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是通明的,咱们也能够选用工厂办法模式。
然而留神当须要生成的产品不多且不会减少,一个具体工厂类就能够实现工作时,可删除形象工厂类。这时工厂办法模式将进化到简略工厂模式。
不论是简略工厂模式还是咱们的工厂办法模式思考的都是一系列雷同类型的产品,如果生产的产品类型不是一个类型,那咱们怎么解决呢,这就须要咱们的工厂模式的另一种模式 - 形象工厂模式。