1. 什么是工厂方法模式
工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。
工厂方法模式定义了一个创建对象的接口,但由子类决定要 实例化的类是哪一个,工厂方法把类的实例化延迟到了子类。
这是对简单工厂的进一步抽象化,弥补了简单工厂对修改开放的缺点。
2. 工厂方法模式的结构
(请允许我无耻的偷了百度百科的图)
如图中所示,工厂方法模式一般有四个角色:
1、抽象工厂角色:这个类是整个工厂方法的核心,所有具体的工厂角色都必须实现这个接口(或者为抽象类)。
2、具体工厂角色:主要用来创建具体的产品,并做相应的逻辑处理。
3、抽象产品角色:所有具体产品的超类。
4、具体的产品角色:实现了抽象产品角色的具体类。
下面请看示例代码:
抽象产品角色:
public interface Shoes {
void type(); //种类
void purpose(); //用途
}
抽象工厂角色:
public interface ShoesFactory {
Shoes createShoes();
}
具体的产品角色:
public class Slipper implements Shoes {
@Override
public void type() {
System.out.println("this is Slipper");
}
@Override
public void purpose() {
System.out.println("become comfortable");
}
}
public class SportShoes implements Shoes {
@Override
public void type() {
System.out.println("this is SportShoes");
}
@Override
public void purpose() {
System.out.println("become faster");
}
}
具体工厂角色:
public class SlipperFactory implements ShoesFactory{
@Override
public Shoes createShoes() {
return new Slipper();
}
}
public class SportShoesFactory implements ShoesFactory {
@Override
public Shoes createShoes() {
return new SportShoes();
}
}
测试类:
public class Client {
public static void main(String[] args){
ShoesFactory sf = new SlipperFactory();
Shoes s = sf.createShoes();
s.type();
s.purpose();
sf = new SportShoesFactory();
s = sf.createShoes();
s.type();
s.purpose();
}
}
输出结果:
3、工厂方法模式和简单工厂模式的比较
简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。比如说,在工厂方法中createShoes()方法提供了一般的框架,以便创建产品,createShoes()方法依赖工厂方法创建具体类,并创建实际的Shoes。简单工厂的做法,可以将对象创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。
4、后记
下面,让我们来看一个黑科技。
抽象工厂角色:
public interface GenericFactory {
<T extends Shoes> Shoes create(Class<T> c); // 泛型方法
}
具体工厂角色:
public class GenericShoesFactory implements GenericFactory{
@Override
public <T extends Shoes> Shoes create(Class<T> c) {
if(c == null){
throw new IllegalArgumentException("argument must not be null");
}
try {
Shoes shoes = c.newInstance();
return shoes;
} catch (Exception e) {
e.printStackTrace();
throw new UnknownError(e.getMessage());
}
}
}
client:
public class Client {
public static void main(String[] args){
GenericFactory gf = new GenericShoesFactory();
gf.create(Slipper.class).type();
}
}
比较:
单个工厂实现类的方法对比前面的多个工厂实现类的方法来说更加的简洁和动态, 而且对于以后新增的产品类来说也能够不用修改原来的代码,符合开闭原则, 但是这种写法在某些情况下是不适用的, 比如不同的 Shoes 对象设置了不同的构造函数,参数都不一样,用反射来实现就不适用了, 这个时候就只能为每一个具体产品类都定义一个对应的具体工厂类了。