定义
该模式有如下三类模式。
1.简单工厂(simple factory)模式:这是程序员的一种简单编程习惯,封装创建同一类不同对象的代码。
2.工厂方法(factory method)模式:定义了一个创建对象的接口,由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
3.抽象工厂(abstract factory)模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
特点
1.工厂提供创建对象接口;
2.创建对象时,只需new对应类的工厂,并调用其创建对象的接口函数即可。
适用范围
创建对象比较繁琐或者不愿暴露创建方法的时候。
一般写法
一般有三种写法,分别为简单工厂、工厂方法、抽象工厂。我们先从简单工厂和工厂方法讲起。为了方便比较,我们先定义两个待会要被工厂创建的对象类,这两个对象类都具有同一个超类Object,如下:
/**
* 类一,继承父类Object
*/
public class ObjectOne extends Object {
// 在构造函数中,打印一下实例化对象时的信息
public ObjectOne() {
System.out.println("I am objectOne!");
}
}
/**
* 类二,继承同个Object父类
*/
public class ObjectTwo extends Object {
// 在构造函数中,打印一下实例化对象时的信息
public ObjectTwo() {
System.out.println("I am objectTwo!");
}
}
- 简单工厂:
/**
* 简单工厂模式,把具有同一超类的类对象
* 创建方法封装到函数createObject中
*/
public class SimpleFactory {
// 简单工厂的创建对象函数,用于创建不同对象
public Object createObject(String type) {
Object object;
if (type.equals("one")) {
// 创建对象一
object = new ObjectOne();
} else if (type.equals("two")) {
// 创建对象二
object = new ObjectTwo();
} else {
// 兜底,假如传错参数返回空
return null;
}
return object;
}
}
- 工厂方法:
在设计模式中,实现一个接口泛指实现某个超类型(可以是类或接口)的某个方法,在如下的方法中就有体现。一个具体的工厂方法只负责一个物品的创建,这里有两个具体工厂负责两个物品的创建。
/**
* 工厂方法定义了一个创建对象的接口
*/
public abstract class FactoryMethod {
// 定义一个实例化函数,实现此接口
// 的子类在此函数实现实例化对象。
// abstract修饰的函数,子类继承必须实现其方法体。
abstract Object createObject();
}
/**
* 工厂方法一只负责对象一的创建
*/
public class FactoryMethodOne extends FactoryMethod{
@Override
public Object createObject() {
return new ObjectOne();
}
}
/**
* 工厂方法二只负责对象二的创建
*/
public class FactoryMethodTwo extends FactoryMethod{
@Override
public Object createObject() {
return new ObjectTwo();
}
}
- 抽象工厂
抽象工厂里面的家族成员具有一定的性质,比如造车,那么家族成员可以是轮子、车窗、方向盘等。
/**
* 抽象工厂,提供一个接口,其中,ObjectOne
* 和ObjectTwo为相关的家族成员
*/
public interface AbstractFactory {
ObjectOne createObjectOne();
ObjectTwo createObjectTwo();
}
/**
* 具体工厂类,实现了抽象工厂的接口,
* 该类必须实现抽象工厂的家族成员创建,
* 家族成员属于不同的类。
*/
public class ConcreteFactory implements AbstractFactory {
@Override
public ObjectOne createObjectOne() {
return new ObjectOne();
}
@Override
public ObjectTwo createObjectTwo() {
return new ObjectTwo();
}
}
工厂模式测试
public class Main {
public static void main(String[] args) {
// 简单工厂创建物品
SimpleFactory simpleFactory = new SimpleFactory();
Object SimpleFactoryObject1 = simpleFactory.createObject("one");
Object SimpleFactoryObject2 = simpleFactory.createObject("two");
// 工厂方法创建物品
FactoryMethod factoryMethodOne = new FactoryMethodOne();
Object factoryMethodOneObject1 = factoryMethodOne.createObject();
FactoryMethod factoryMethodTwo = new FactoryMethodTwo();
Object factoryMethodOneObject2 = factoryMethodTwo.createObject();
// 抽象工厂创建物品
AbstractFactory concreteFactory = new ConcreteFactory();
ObjectOne concreteFactoryObject1 = concreteFactory.createObjectOne();
ObjectTwo concreteFactoryObject2 = concreteFactory.createObjectTwo();
}
}
I am objectOne!
I am objectTwo!
I am objectOne!
I am objectTwo!
I am objectOne!
I am objectTwo!
为什么需要工厂模式
1.创建对象时,我们只需关心工厂对外暴露的接口createObject即可,至于该函数怎么创建对象我们不需要知道,这就是做到了创建对象与实现对象类的解耦。
2.工厂方法中,new一个工厂,调用一次createObject,不是很繁琐吗?以ObjectOne为例,直接new ObjectOne()不行吗?如下所示:
FactoryMethod factoryMethodOne = new FactoryMethodOne();
Object factoryMethodOneObject1 = factoryMethodOne.createObject();
Object factoryMethodOneObject1 = new ObjectOne();
当你ObjectOne需要很复杂地被创建时就不行了,比如ObjectOne类对象的创建要依赖很多其他对象的时候,全部写在当前显然不好看,且创建与实现的耦合度高,而最终我们也只关心ObjectOne,假设我们有PartOne和PartTwo两类,ObjectOne依赖于这两类的对象,全部写在当前如下所示:
PartOne part1 = new PartOne();
PartTwo part2 = new PartTwo();
Object factoryMethodOneObject1 = new ObjectOne(part1, part2);
而写成工厂方法的时候,只需要改造工厂即可,形式如下:
public class FactoryMethodOne extends FactoryMethod{
@Override
public Object createObject() {
PartOne part1 = new PartOne();
PartTwo part2 = new PartTwo();
new ObjectOne(part1, part2);
}
}
这样依旧只new一个工厂,调用createObjectOne()即可。这就是创建与实现的解耦。
FactoryMethod factoryMethodOne = new FactoryMethodOne();
Object factoryMethodOneObject1 = factoryMethodOne.createObject();
3.再利用抽象工厂把PartOne和PartTwo封装,如下:
public interface PartsAbstractFactory {
PartOne createPartOne();
partTwo createPartTwo();
}
public class Parts implements PartsAbstractFactory {
@Override
public PartOne createPartOne() {
return new PartOne();
}
@Override
public PartTwo createPartTwo() {
return new PartTwo();
}
}
那么第2点的FactoryMethodOne可以改造如下:
public class FactoryMethodOne extends FactoryMethod{
@Override
public Object createObject() {
PartsAbstractFactory parts = new Parts();
new ObjectOne(parts);
}
}
/**
* 相应地,ObjectOne要做如下改造
* 即可获得PartOne和PartTwo的对象
*/
public class ObjectOne extends Object {
privarte PartOne part1;
privarte PartTwo part2;
public ObjectOne(PartsAbstractFactory parts) {
System.out.println("I am objectOne!");
this.part1 = parts.createPartOne();
this.part = parts.createPartTwo();
}
}
看到这里是不是觉得似乎明白了抽象工厂的作用,它就是把ObjectOne所依赖的对象整到一起,然后只需要new一个工厂,调用相应的创建对象函数即可。当产品的依赖家族稳定很少变化的时候可以试试抽象工厂,如果产品的依赖家族种类频繁变化,抽象工厂提供的方法也频繁变化,那实现其接口的子类将会很繁琐,这样就不建议了。