我们通过实例进行讲解,总觉得概念比较抽象,还是直接看代码比较直接。
一、简单工厂
举例:一个工厂要生产两种品牌的车,车的功能是可以用来开。
首先定义一个接口,车是用来开的。
icar.h
#pragma once
class ICar
{
public:
virtual ~ICar() {}
virtual void drive() = 0;
};
奔驰车是这样开的:
benzCar.h
#pragma once
#include "icar.h"
#include <iostream>
class BenzCar : public ICar
{
public:
void drive() override
{
std::cout << "开奔驰" << std::endl;
}
};
宝马车是这样开的:
bmwCar
#pragma once
#include "icar.h"
#include <iostream>
class BmwCar : public ICar
{
public:
void drive() override
{
std::cout << "开宝马" << std::endl;
}
};
我们看看这个汽车厂是怎样生产的:
carFactory.h
#pragma once
#include "icar.h"
#include "benzCar.h"
#include "bmwCar.h"
enum CarBrand
{
BenzBand,
BmwBand
};
class CarFactory
{
public:
ICar *produce(CarBrand carBand)
{
switch (carBand)
{
case BenzBand:
return new BenzCar();
break;
case BmwBand:
return new BmwCar();
break;
default:
break;
}
return nullptr;
}
};
测试程序:
#include "carFactory.h"
int main()
{
CarFactory *carFactory = new CarFactory();
ICar *benzCar = carFactory->produce(BenzBand);
benzCar->drive();
ICar *BmwCar = carFactory->produce(BmwBand);
BmwCar->drive();
delete carFactory;
delete benzCar;
delete BmwCar;
getchar();
return 0;
}
运行结果 :
开奔驰
开宝马
简单工厂果然是简单,一个工厂就做了所有创建的活,通过switch进行创建不同类型的对象。这就造成了工厂类的职责过重。如果要增加一个类型,就需要修改工厂类的实现,则违反了开闭原则。
我们能不能通过添加类的方法,对其进行扩展,每增加一个新的车型,不需要再修改原来的代码,只需要增加新类实现?
答案是可以的,下面我们看工厂方法。
二、工厂方法
现在觉得再开一个厂,每个厂只生产一款车型。
icar.h
#pragma once
class ICar
{
public:
virtual ~ICar() {}
virtual void Drive() = 0;
};
benzCar.h
#pragma once
#include "icar.h"
#include <iostream>
class BenzCar : public ICar
{
public:
void Drive() override
{
std::cout << "开奔驰" << std::endl;
}
};
bmwCar.h
#pragma once
#include "icar.h"
#include <iostream>
class BmwCar : public ICar
{
public:
void Drive() override
{
std::cout << "开宝马" << std::endl;
}
};
到目前为止,上面的代码和简单工厂中的代码一模一样。
以下就是不同点了。
现在需要一个工厂类接口,两个厂都需要实现的接口。
iCarFactory.h
#pragma once
#include "icar.h"
class ICarFactory
{
public:
virtual ~ICarFactory() {}
virtual ICar *produce() = 0;
};
奔驰工厂生产奔驰车
benzCarFactory.h
#pragma once
#include "benzCar.h"
#include "iCarFactory.h"
class BenzCarFactory : public ICarFactory
{
public:
ICar *produce() override
{
return new BenzCar();
}
};
宝马工厂生产宝马车
bmwCarFactory.h
#pragma once
#include "icar.h"
#include "benzCar.h"
#include "bmwCar.h"
#include "iCarFactory.h"
class BmwCarFactory : public ICarFactory
{
public:
ICar *produce() override
{
return new BenzCar();
}
};
客户端代码:
main.cpp
#include "benzCarFactory.h"
#include "bmwCarFactory.h"
int main()
{
ICarFactory *benzFactory = new BenzCarFactory();
ICar *benzCar = benzFactory->produce();
benzCar->Drive();
ICarFactory *bmwFactory = new BmwCarFactory();
ICar *bmwCar = bmwFactory->produce();
bmwCar->Drive();
delete benzFactory;
delete benzCar;
delete bmwFactory;
delete bmwCar;
getchar();
return 0;
}
我们新增加一个品牌的车,就从抽象工厂继承实现一个具体工厂,这样就会有这样的困扰,由于每个工厂只生产一种车,每增加一种车,就需要重新建一个新的工厂。
三、抽象工厂
奔驰厂只生产奔驰车,奔驰的CEO说,我们要多生产几个系列的车,有运动系列,和商务系列的车型。宝马厂的CEO看到奔驰厂的这几款系列车型热销,于是决定也跟上脚步,也生产运动和商务两个系列车型。
运行系列车需要实现的接口
iSportCar.h
#pragma once
class ISportCar
{
public:
virtual ~ISportCar() {}
virtual void doSport() = 0;
};
奔驰运行系列车
benzSportCar.h
#pragma once
#include "iSportCar.h"
#include <iostream>
class BenzSportCar : public ISportCar
{
public:
void doSport() override
{
std::cout << "奔驰运动型汽车,开着就是不一样..." << std::endl;
}
};
宝马运行系列车
bmwSportCar.h
#pragma once
#include "iSportCar.h"
#include <iostream>
class bmwSportCar : public ISportCar
{
public:
void doSport() override
{
std::cout << "宝马运动型汽车,开着就是不一样..." << std::endl;
}
};
商务车需要实现的接口
iBusinessCar.h
#pragma once
class IBusinessCar
{
public:
virtual ~IBusinessCar() {}
virtual void doBusiness() = 0;
};
奔驰商务车
benzBusinessCar.h
#pragma once
#include "iBusinessCar.h"
#include <iostream>
class BenzBusinessCar : public IBusinessCar
{
public:
void doBusiness() override
{
std::cout << "奔驰商务车,就是宽敞..." << std::endl;
}
};
宝马商务车
bmwBusinessCar.h
#pragma once
#include "iBusinessCar.h"
#include <iostream>
class BmwBusinessCar : public IBusinessCar
{
public:
void doBusiness() override
{
std::cout << "宝马商务车,就是宽敞..." << std::endl;
}
};
工厂接口:
iCarFactory.h
#pragma once
#include "iSportCar.h"
#include "iBusinessCar.h"
class ICarFactory
{
public:
virtual ~ICarFactory() {}
//生产运动型汽车
virtual ISportCar * produceSportCar() = 0;
//生产商务型型汽车
virtual IBusinessCar * produceBusinessCar() = 0;
};
奔驰厂
benzCarFactory.h
#pragma once
#include "iCarFactory.h"
#include "benzSportCar.h"
#include "benzBusinessCar.h"
class BenzCarFactory : public ICarFactory
{
public:
//生产运动型汽车
ISportCar * produceSportCar() override
{
return new BenzSportCar();
}
//生产商务型型汽车
IBusinessCar * produceBusinessCar() override
{
return new BenzBusinessCar();
}
};
宝马厂:
#pragma once
#include "iCarFactory.h"
#include "bmwSportCar.h"
#include "bmwBusinessCar.h"
class BmwCarFactory : public ICarFactory
{
public:
//生产运动型汽车
ISportCar * produceSportCar() override
{
return new bmwSportCar();
}
//生产商务型型汽车
IBusinessCar * produceBusinessCar() override
{
return new BmwBusinessCar();
}
};
客户端代码:
main.cpp
#include "benzCarFactory.h"
#include "bmwCarFactory.h"
int main()
{
ICarFactory * benzCarFactory = new BenzCarFactory();
ISportCar *benzSportCar = benzCarFactory->produceSportCar();
benzSportCar->doSport();
IBusinessCar *benzBusinessCar = benzCarFactory->produceBusinessCar();
benzBusinessCar->doBusiness();
ICarFactory * bmwCarFactory = new BmwCarFactory();
ISportCar *bmwSportCar = bmwCarFactory->produceSportCar();
bmwSportCar->doSport();
IBusinessCar *bmwBusinessCar = bmwCarFactory->produceBusinessCar();
bmwBusinessCar->doBusiness();
delete benzCarFactory;
delete benzSportCar;
delete benzBusinessCar;
delete bmwCarFactory;
delete bmwSportCar;
delete bmwBusinessCar;
getchar();
return 0;
}
对比工厂方法和抽象工厂发现,工厂方法是每个工厂生产一种对象,而抽象工厂是一个具体工厂生产几个不同类型(系列)。
参考的这篇比较好,里面的概念说得比较清楚,本文是按照我自己的理解进行例子的改写。如果大家要想对这几个模式的概念进行理解的话可以参考下面的博文。
参考:
简单工厂、工厂方法、抽象工厂区别
简单工厂,工厂方法,抽象工厂的区别与联系
浅谈简单工厂,工厂方法,抽象工厂的区别和使用
简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别