简单工厂、工厂方法和抽象工厂的区别
烟雨星空 人气:2工厂模式一般分为简单工厂、工厂方法和抽象工厂三种,看了很多资料,好多讲的都是云里雾里的。要么是概念太多,让人看得一脸懵逼,要么是举得例子不太恰当,看了更让人迷惑了。经过自己一番研究,通过一个简单的例子,终于搞明白了它们之间的区别。
下面以生产宝马、奔驰汽车的工厂为例,讲解它们之间的区别。
一、简单工厂模式
创建一个工厂类,根据传入的参数来决定创建哪个汽车类
//汽车接口
public interface Car {
void getCar();
}
//宝马汽车类
public class BMWCar implements Car {
@Override
public void getCar() {
System.out.println("这是宝马车");
}
}
//奔驰汽车类
public class BenzCar implements Car {
@Override
public void getCar() {
System.out.println("这是奔驰车");
}
}
//工厂类,用于决定创建哪一个具体的汽车类
public class DefaultFactory {
public Car produce(String name){
if(name.equals("benz")){
return new BenzCar();
}else if(name.equals("bmw")){
return new BMWCar();
}
return null;
}
}
public class FTest {
public static void main(String[] args) {
DefaultFactory factory = new DefaultFactory();
Car car = factory.produce("bmw");
car.getCar(); //这是宝马车
Car benz = factory.produce("benz");
benz.getCar(); //这是奔驰车
}
}
可以看到,在具体的工厂类DefaultFactory中,我们根据传入的name来决定创建哪一个汽车类。当需要创建宝马时,传入bmw,当需要创建奔驰时传入benz。思考一下,如果我需要创建一个大众汽车呢。是不是需要创建一个大众汽车类实现Car接口,还需要修改工厂类的produce方法,新增一个大众的分支。 再回忆一下,之前讲过的软件六大设计原则之一开闭原则。很明显,这违背了开闭原则(对修改是关闭的)。
于是,有了下边的工厂方法,可以保证遵循开闭原则。
二、工厂方法模式
工厂方法,相比于简单工厂,多了一个角色——工厂接口,负责定义生产汽车的公共接口,然后每个工厂实现类都去实现这个接口。
//工厂接口
public interface IFactory {
Car produce();
}
//宝马生产工厂
public class BMWFactory implements IFactory{
@Override
public Car produce() {
return new BMWCar();
}
}
//奔驰生产工厂
public class BenzFactory implements IFactory {
@Override
public Car produce() {
return new BenzCar();
}
}
public class FacTest {
public static void main(String[] args) {
BMWFactory bmwFactory = new BMWFactory();
bmwFactory.produce().getCar(); //这是宝马车
BenzFactory benzFactory = new BenzFactory();
benzFactory.produce().getCar(); //这是奔驰车
}
}
可以看到,我把之前的一个工厂,拆分为两个工厂。当具体需要哪个汽车的时候,就去实例化它对应的工厂。这样,当再需要大众车的时候,我只需要添加一个大众车的类和大众车对应的工厂实现类去实现IFactory接口就可以了。不需要修改原来的代码,这就符合开闭原则了。
三、 抽象工厂模式
初识抽象工厂的同学,总是很迷惑它和工厂方法有什么区别,不就是在工厂实现类里多了几个方法吗。其实,抽象工厂是对工厂方法的升级,用于创建一组相互关联或相互依赖的对象。
在此需要了解一下产品等级和产品族的关系。假如有一个汽车制造商,它只生产低配版的汽车产品(至于为什么,我猜是低配版更亲民,销量更高吧,哈哈),其中就包括低配宝马和低配奔驰。还有一个汽车制造商只生产高配版的汽车(没什么原因,就是钱多任性,高端大气上档次),如高配宝马和高配奔驰。
我们就把高配制造商或者低配制造商称为一个产品族。而其中的低配宝马和低配奔驰属于同一个产品等级,高配宝马和高配奔驰属于同一个产品等级。
画一张图来理解一下它们的概念,横向是三个产品族,纵向是两个产品等级。
代码如下:
//工厂接口,包含两个方法,创建宝马和创建奔驰
public interface IFactory {
Car produceBMW();
Car produceBenz();
}
//-------- 高配车和工厂实现类 -------//
public class HighBMW implements Car {
@Override
public void getCar() {
System.out.println("高配宝马车");
}
}
public class HighBenz implements Car {
@Override
public void getCar() {
System.out.println("高配奔驰车");
}
}
public class HighFactory implements IFactory {
@Override
public Car produceBMW() {
return new HighBMW();
}
@Override
public Car produceBenz() {
return new HighBenz();
}
}
//-------- 低配车和工厂实现类 ----------//
public class LowBMW implements Car {
@Override
public void getCar() {
System.out.println("低配宝马车");
}
}
public class LowBenz implements Car {
@Override
public void getCar() {
System.out.printf("低配奔驰车");
}
}
public class LowFactory implements IFactory {
@Override
public Car produceBMW() {
return new LowBMW();
}
@Override
public Car produceBenz() {
return new LowBenz();
}
}
public class AbsTest {
public static void main(String[] args) {
HighFactory highFactory = new HighFactory();
highFactory.produceBMW().getCar(); //高配宝马车
highFactory.produceBenz().getCar(); //高配奔驰车
LowFactory lowFactory = new LowFactory();
lowFactory.produceBMW().getCar(); //低配宝马车
lowFactory.produceBenz().getCar(); //低配奔驰车
}
}
乍一看,抽象工厂和工厂方法特别的相似,其实这里边就是多了一个产品族的概念,它强调一个产品族的对象应该放到同一个工厂类里边。比如,我再需要一个中配版或者豪华版的汽车制造商,只需要实现它的具体工厂类和相应的各同等级的汽车类。
总结:
- 简单工厂顾明思议,实现比较简单,只需要传入一个特定参数即可,不用知道具体的工厂实现类名,缺点就是违背了开闭原则。
- 工厂方法和抽象工厂,遵守开闭原则,解耦了类关系。但是,扩展比较复杂,需要增加一系列的类。
- 需要注意,工厂方法和抽象工厂的区别就在于,抽象工厂关注于某一个产品族,当产品对象之间是有关联关系的一个产品族时用这种方式,而工厂方法没有产品族的概念。
加载全部内容