工厂方法(模式)
前面,我们讲解了简单工厂模式,接着我们来说工厂方法模式。今天我们从一个简单的例子来说,从无模式发现代码中问题,然后使用模式解决的
方式。
需求
我们要实现一个文件分割器,把大文件按照指定的文件个数,分割成小的文件。文件的格式为二进制文件
示意代码如下:
/**
* 接口描述: 文件分割器接口
*/
public interface ISplitter {
void split(String filePath,int fileNumber);
}
/**
* 类描述: 二进制文件分割
*/
public class BinarySplitter implements ISplitter{
@Override
public void split(String filePath, int fileNumber) {
System.out.println("this is BinarySplitter filePath::::::"+filePath+" fileNumber::::::"+fileNumber);
}
}
/**
* 类描述: 文件分割器窗体
*/
public class SplitterMainForm {
// 文件路径
private String filePath;
// 文件被分割的个数
private int fileNumber;
// 点击按钮
public void onClick(String filePath,int fileNumber) {
// SplitterMainForm 依赖具体的BinarySplitter分割器。
ISplitter splitter = new BinarySplitter();
splitter.split(filePath,fileNumber);
}
}
上述代码中文件分割器窗体SplitterMainForm类依赖了具体BinarySplitter分割器,
我们知道这种强耦合关系导致代码很脆弱,不好。那么我们该如何解决这个问题呢?
重构v2
思考:现在问题是SplitterMainForm依赖具体的BinarySplitter分割器。我们想办法不让它依赖具体实现类问题就解决了
因此:我们创建ISplitter的工厂接口类ISplitterFactory。在这里我只展示新增的代码和修改的代码
新增ISplitterFactory接口
/**
* 类描述: 文件分割器工厂接口
*/
public interface ISplitterFactory {
public ISplitter createSplitter();
}
/**
* 类描述: 二进制文件分割器工厂
*/
public class BinarySplitterFactory implements ISplitterFactory{
@Override
public ISplitter createSplitter() {
return new BinarySplitter();
}
}
/**
* 类描述: 文件分割器窗体
*/
public class SplitterMainForm {
// 文件路径
private String filePath;
// 文件被分割的个数
private int fileNumber;
private ISplitterFactory splitterFactory;
public SplitterMainForm(String filePath,int fileNumber,ISplitterFactory splitterFactory) {
this.filePath = filePath;
this.fileNumber = fileNumber;
this.splitterFactory = splitterFactory;
}
// 点击按钮
public void onClick(String filePath,int fileNumber) {
// SplitterMainForm 依赖抽象ISplitterFactory接口。
ISplitter splitter = splitterFactory.createSplitter();
splitter.split(filePath,fileNumber);
}
}
问题SplitterMainForm依赖具体的BinarySplitter分割器解决,现在SplitterMainForm 依赖抽象ISplitterFactory接口。
疑问:虽然SplitterMainForm类现在不依赖具体工厂类,是通过参数的形式传递过来的,那么肯定在某个代码的位置,还是要创建具体的工厂,
那么问题不又回来了嘛。是的,确实是在某个地方又出现了依赖具体类。然而,我们知道软件设计模式,是封装变化,而不是消缺变化。变化我们
是消除不了的,我们只能把变化赶到一起集中管理起来。某软件知名大师曾经说过,把猫关进笼子里。例如整洁的房间,好动的猫,
如何保证房间的整洁,那就把它关在笼子里
定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使得一个类的实例化延迟(目的:解耦)到子类。
通俗说
它为类提供了一种把实例化的逻辑委托给子类的方式。
维基百科
在基于类的编程中,工厂方法模式是一种创建型设计模式用来解决创建对象的问题,而不需要指定将要创建对象的确切类。
这是通过调用工厂方法创建对象来完成的,而不是通过调用构造器。该工厂方法在接口中指定并由子类实现,或者在基类实现并可以选择由子类重写。
JAVA案例
java.util.Calendar
java.util.ResourceBundle
java.text.NumberFormat
java.nio.charset.Charset
java.net.URLStreamHandlerFactory
java.util.EnumSet
javax.xml.bind.JAXBContext
总结
- 工厂方法模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
- 工厂方法模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好的解决了这种紧耦合关系。
- 工厂方法模式解决"单个对象"的需求变化,缺点在于要求创建方法/参数相同。