一、简单工厂模式
创建一个工厂类(水果工厂),根据我们的传入参数来决定生产何种类型的产品(水果),这样,就不用我们自己去new了,不用关心对象是怎么创建的,我们只需要对象
- 适合工厂类负责创建的对象比较少的情况
#include <iostream>
using namespace std;
class AbstractFruit {
public:
virtual void Name() = 0;
};
class Apple : public AbstractFruit {
public:
void Name() {
cout << "apple\n";
}
};
class Banana : public AbstractFruit {
public:
void Name() {
cout << "Banana\n";
}
};
// 水果工厂
class FruitFactory {
public:
// 静态方法,不用创建对象,方便调用
static AbstractFruit* CreateFruit(string flag) {
if (flag == "apple") {
return new Apple;
}
else if (flag == "banana") {
return new Banana;
}
else {
return nullptr;
}
}
};
void test() {
FruitFactory* factory = new FruitFactory;
AbstractFruit* papple = factory->CreateFruit("apple");
papple->Name();
delete papple; // 注意delete的顺序,先new的后delete
delete factory;
}
int main() {
test();
return 0;
}
这种方式的缺点是工厂创建对象的过程中,是通过 if-else 的结构去判断要生产何种类型的产品的,如果新增了一个产品,那么就要去修改生产对象的代码,违背了开闭原则。
二、工厂方法模式
为了让工厂类符合开闭原则,于是将其抽象出来成为抽象工厂,再让一个具体的产品对应一个具体的工厂。
- 类会变多,难维护
#include <iostream>
using namespace std;
class AbstractFruit {
public:
virtual void Name() = 0;
};
class Apple : public AbstractFruit {
public:
void Name() {
cout << "apple\n";
}
};
class Banana : public AbstractFruit {
public:
void Name() {
cout << "Banana\n";
}
};
// 水果工厂
class AbstractFruitFactory {
public:
virtual AbstractFruit* Create() = 0;
};
class appleFactory : public AbstractFruitFactory{
public:
AbstractFruit* Create() {
return new Apple;
}
};
class bananaFactory : public AbstractFruitFactory{
public:
AbstractFruit* Create() {
return new Banana;
}
};
void test() {
AbstractFruitFactory* factory = new appleFactory;
AbstractFruit* fruit = factory->Create();
fruit->Name();
delete fruit;
delete factory;
factory = new bananaFactory;
AbstractFruit* fruit = factory->Create();
fruit->Name();
delete fruit;
delete factory;
}
int main() {
test();
return 0;
}
三、抽象工厂模式
抽象工厂针对的是产品族,而不是产品结构
- 产品族:同一产地或同一厂商,功能不同
- 产品等级:功能相同,产地或厂商不同
在下面的例子中,抽象出苹果类和香蕉类,中国苹果和美国苹果继承苹果类,中国香蕉和美国香蕉继承香蕉类。再抽象出工厂类,中国工厂继承工厂类,生产中国苹果和中国香蕉;美国工厂继承工厂类,生产美国苹果和美国香蕉
#include <iostream>
using namespace std;
class AbstractApple {
public:
virtual void Name() = 0;
};
class AbstractBanana {
public:
virtual void Name() = 0;
};
class CHN_Apple : public AbstractApple {
public:
void Name() {
cout << "china apple\n";
}
};
class CHN_Banana : public AbstractBanana {
public:
void Name() {
cout << "china Banana\n";
}
};
class USA_Apple : public AbstractApple {
public:
void Name() {
cout << "USA apple\n";
}
};
class USA_Banana : public AbstractBanana {
public:
void Name() {
cout << "USA Banana\n";
}
};
class AbstractFactory {
public:
virtual AbstractApple* createApple() = 0;
virtual AbstractBanana* createBanana() = 0;
};
class CHN_Factory : public AbstractFactory {
public:
virtual AbstractApple* createApple() {
return new CHN_Apple;
}
virtual AbstractBanana* createBanana() {
return new CHN_Banana;
}
};
class USA_Factory : public AbstractFactory {
public:
AbstractApple* createApple() {
return new USA_Apple;
}
AbstractBanana* createBanana() {
return new USA_Banana;
}
};
void test() {
AbstractFactory* factory = new CHN_Factory;
AbstractApple* apple = factory->createApple();
AbstractBanana* banana = factory->createBanana();
apple->Name();
banana->Name();
delete banana;
delete apple;
delete factory;
factory = new USA_Factory;
apple = factory->createApple();
banana = factory->createBanana();
apple->Name();
banana->Name();
delete banana;
delete apple;
delete factory;
}
int main() {
test();
return 0;
}
所以如果想增加西瓜这个产品时,只需要去增加代码即可,也就是抽象出西瓜类,再让各国的西瓜继承它,对应各国创建一个产生西瓜的工厂,其他代码是不需要去修改的,符合开闭原则。