一、介绍:
1、定义:
问题引入:简单工厂模式中类的创建依赖工厂类,如果想要拓展程序必须对工厂类进行修改,这违背了闭包原则。可以创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。工厂方法模式也即将简单工厂模块的Factory工厂类拆成接口,再定义具体的工厂子类去实现。
2、结构组成:工厂方法模式包含四个部分:
(1)抽象工厂类;
(2)具体工厂类;
(3)
抽象产品类
(4)
具体产品类
。
3、代码实现:
/**
* 虚拟工厂类
* 给具体的工厂类提供虚拟方法
*/
abstract class AbstractFactory {
// 表示创建产品的方法,此处使用的是通过具体的产品类的Class来确定需要创建的产品
// 也可以通过String等其他方式来指定
public abstract <T extends AbstractProduct> T create(Class<T> tClass);
}
/**
* 具体工厂类
* 继承虚拟工厂类,提供真正的创建对象的方法的实现
*/
class CommonFactory extends AbstractFactory{
@Override // 对虚拟工厂类的方法进行重写
public <T extends AbstractProduct> T create(Class<T> tClass) {
T product = null; // 创建一个null对象作为初始化,使catch到异常后也能有null返回作为结果
try {
// 明明这样就可以实现,但是书里写的更加复杂
// (T)Class.forName(tClass.getName()).newInstance()
// 暂时对此感到不解
product = tClass.newInstance(); // 通过反射创建新的对象
} catch (Exception e) {
e.printStackTrace();
}
return product;
}
}
/**
* 虚拟产品类
* 对产品类的属性以及方法做好规范
* 如果有所有具体产品类都通用的方法也可以直接实现
*/
abstract class AbstractProduct {
/**
* 通用方法
*/
public void method1() {
System.out.println("所有产品都会这么做");
}
/**
* 每个产品实现各异的方法
*/
public abstract void method2();
}
/**
* 具体产品类
* 继承虚拟产品类,在虚拟产品类提供的默认方法外,具体实现虚拟类中规定的虚拟方法
*/
class Product extends AbstractProduct {
@Override
public void method2() {
System.out.println("这是一个具体的产品类的特性");
}
}
//客户端
class Client {
public static void main(String[] args) {
AbstractFactory factory = new CommonFactory();
AbstractProduct product = factory.create(Product.class);
product.method1();
product.method2();
}
}
二、demo:
1、图片读取器:
(1)工厂
public interface IReaderFactory {
IImageReader getIReader(String args);
}
(2)具体工厂
/**
* GIF图片读取器工厂类
*/
public class GifRFactory implements IReaderFactory {
Logger logger = LoggerFactory.getLogger(GifRFactory.class);
@Override
public IImageReader getIReader(String args) {
GifIReader gifIReader = new GifIReader();
logger.info("创建GIF图片读取器成功!");
return gifIReader;
}
}
/**
* JPG图片读取器工厂类
*/
public class JpgRFactory implements IReaderFactory {
Logger logger = LoggerFactory.getLogger(JpgRFactory.class);
@Override
public IImageReader getIReader(String args) {
JpgIReader jpgIReader = new JpgIReader();
logger.info("创建JPG图片读取器成功!");
return jpgIReader;
}
}
(3)抽象产品:
/**
* 图片读取器接口
*/
public interface IImageReader {
void reader(String args);
}
(4)具体产品:
public class GifIReader implements IImageReader {
Logger logger = LoggerFactory.getLogger(GifIReader.class);
@Override
public void reader(String args) {
logger.info("读取GIF格式图片!");
}
}
public class JpgIReader implements IImageReader {
Logger logger = LoggerFactory.getLogger(JpgIReader.class);
@Override
public void reader(String args) {
logger.info("读取JPG格式图片!");
}
}
客户端:
public class ApiTest {
Logger logger = LoggerFactory.getLogger(ApiTest.class);
@Test
public void factoryTest(){
IReaderFactory iReaderFactory;
IImageReader imageReader;
// 可以配置XML文件,通过读取配置文件,获取需要的图片读取器,使得程序更加符合开闭原则。
logger.info("读取配置文件获取需要的图片格式读取器工厂类");
iReaderFactory = new GifRFactory();
logger.info("获取GIF图片读取器");
imageReader = iReaderFactory.getIReader("args");
logger.info("调用GIF图片读取图片");
imageReader.reader("args");
}
}