前提
当逻辑较为简单时,可以直接创建对应的类。代码如下:
#include<iostream>
using namespace std;
class apple
{
public:
void eat()
{
cout<<"吃苹果"<<endl;
}
};
class banana
{
public:
void eat()
{
cout<<"吃香蕉"<<endl;
}
};
class pear
{
public:
void eat()
{
cout<<"吃梨"<<endl;
}
};
int main()
{
apple m_apple;
m_apple.eat();
banana m_banana;
m_banana.eat();
pear m_pear;
m_pear.eat();
system("pause");
return 0;
}
通过此代码可以发现,用户直接与客户接触,违背了DIP(依赖倒转)原则,过于麻烦,所以引出简单工厂模式。
简单工厂模式
#include<iostream>
using namespace std;
#include<string>
class Fruit
{
public:
virtual void eat() = 0;
};
class apple:public Fruit
{
public:
void eat()
{
cout<<"吃苹果"<<endl;
}
};
class banana:public Fruit
{
public:
void eat()
{
cout<<"吃香蕉"<<endl;
}
};
class pear:public Fruit
{
public:
void eat()
{
cout<<"吃梨"<<endl;
}
};
class factory
{
public:
Fruit *createFruit(string name)
{
if(name=="苹果")
{
fruit = new apple;
}
if(name=="香蕉")
{
fruit = new banana;
}
if(name=="梨")
{
fruit = new pear;
}
return fruit;
}
private:
Fruit *fruit;
};
int main()
{
factory m_factory;
string apple = "苹果";
string banana = "香蕉";
string pear = "梨";
Fruit *m_apple = m_factory.createFruit(apple);
m_apple->eat();
Fruit *m_banana = m_factory.createFruit(banana);
m_banana->eat();
Fruit *m_pear = m_factory.createFruit(pear);
m_pear->eat();
system("pause");
return 0;
}
在简单工厂模式中,用户直接与factory(工厂)交互,而不与产品(水果)交互,体现了DIP原则,但是当需要添加新的产品时,需要在factory中修改代码,这不符合OCP(开闭原则),因此引入工厂模式
工厂模式
#include<iostream>
using namespace std;
#include<string>
class Fruit
{
public:
virtual void eat() = 0;
};
class apple:public Fruit
{
public:
void eat()
{
cout<<"吃苹果"<<endl;
}
};
class banana:public Fruit
{
public:
void eat()
{
cout<<"吃香蕉"<<endl;
}
};
class pear:public Fruit
{
public:
void eat()
{
cout<<"吃梨"<<endl;
}
};
class factory
{
public:
virtual Fruit *createFruit()=0;
};
class appleFactory:public factory
{
public:
Fruit *createFruit()
{
return new apple;
}
};
class bananaFactory:public factory
{
public:
Fruit *createFruit()
{
return new banana;
}
};
class pearFactory:public factory
{
public:
Fruit *createFruit()
{
return new pear;
}
};
int main()
{
factory *m_appleFactory = new appleFactory;
Fruit *m_apple = m_appleFactory->createFruit();
m_apple->eat();
factory *m_bananaFactory = new bananaFactory;
Fruit *m_banana = m_bananaFactory->createFruit();
m_banana->eat();
factory *m_pearFactory = new pearFactory;
Fruit *m_pear = m_pearFactory->createFruit();
m_pear->eat();
system("pause");
return 0;
}
在工厂模式中,每个工厂都对应一个特定的产品,当需要添加新的产品时,只需要继承产品类和继承工厂类即可,这体现可OCP原则,解决了简单工厂的问题。但是当产品族和产品等级结构较复杂时,这时需要使用抽象工厂模式。下面介绍产品族和产品等级结构。
产品族和产品等级结构
红色框为一个产品族,代表中国的苹果、中国的香蕉和中国的梨。
蓝色框为一个产品等级结构,代表中国的苹果、美国的苹果和英国的苹果
抽象工厂模式
如果使用工厂模式实现上图,需要对每个国家的每种水果都需要创建一个工厂,总共需要9个工厂。但是在抽象工厂模式中,仅需使用三个抽象工厂即可完成任务,代码如下:
#include<iostream>
using namespace std;
#include<string>
//抽象层
class Apple
{
public:
virtual void eat() = 0;
};
class Banana
{
public:
virtual void eat() = 0;
};
class Pear
{
public:
virtual void eat() = 0;
};
class Factory
{
public:
virtual Apple *eatApple()=0;
virtual Banana *eatBanana()=0;
virtual Pear *eatPear()=0;
};
//架构层
class Eat
{
public:
void eatAll(Apple *apple,Banana *banana,Pear *pear)
{
m_apple = apple;
m_banana = banana;
m_pear = pear;
}
void show()
{
m_apple->eat();
m_banana->eat();
m_pear->eat();
}
private:
Apple *m_apple;
Banana *m_banana;
Pear *m_pear;
};
//实现层
//中国的水果
class ChinaApple:public Apple
{
public:
void eat()
{
cout<<"吃中国苹果"<<endl;
}
};
class ChinaBanana:public Banana
{
public:
void eat()
{
cout<<"吃中国香蕉"<<endl;
}
};
class ChinaPear:public Pear
{
public:
void eat()
{
cout<<"吃中国梨"<<endl;
}
};
class ChinaFactory:public Factory
{
public:
Apple *eatApple()
{
return new ChinaApple;
}
Banana *eatBanana()
{
return new ChinaBanana;
}
Pear *eatPear()
{
return new ChinaPear;
}
};
//美国的水果
class USAApple:public Apple
{
public:
void eat()
{
cout<<"吃美国苹果"<<endl;
}
};
class USABanana:public Banana
{
public:
void eat()
{
cout<<"吃美国香蕉"<<endl;
}
};
class USAPear:public Pear
{
public:
void eat()
{
cout<<"吃美国梨"<<endl;
}
};
class USAFactory:public Factory
{
public:
Apple *eatApple()
{
return new USAApple;
}
Banana *eatBanana()
{
return new USABanana;
}
Pear *eatPear()
{
return new USAPear;
}
};
//英国的水果
class UKApple:public Apple
{
public:
void eat()
{
cout<<"吃英国苹果"<<endl;
}
};
class UKBanana:public Banana
{
public:
void eat()
{
cout<<"吃英国香蕉"<<endl;
}
};
class UKPear:public Pear
{
public:
void eat()
{
cout<<"吃英国梨"<<endl;
}
};
class UKFactory:public Factory
{
public:
Apple *eatApple()
{
return new UKApple;
}
Banana *eatBanana()
{
return new UKBanana;
}
Pear *eatPear()
{
return new UKPear;
}
};
int main()
{
//中国苹果、美国香蕉和英国梨
//中国苹果
Factory *chinaFactory = new ChinaFactory;
Apple *chinaApple = chinaFactory->eatApple();
//美国香蕉
Factory *usaFactory = new USAFactory;
Banana *usaBanana = usaFactory->eatBanana();
//英国梨
Factory *ukFactory = new UKFactory;
Pear *ukPear = ukFactory->eatPear();
Eat eat;
eat.eatAll(chinaApple,usaBanana,ukPear);
eat.show();
system("pause");
return 0;
}
当需要添加产品族时,只需要在原有Factory(工厂)基础上继承新的Factory,符合OCP原则。
但是当需要添加新的产品等级结构时,需要修改抽象类中的代码,不符合OCP原则,所有抽象工厂模式适用于产品等级结构确定的情况使用。
工厂三兄弟总结
简单工厂模式不是Gof中的,但是由于其使用方便,所以目前也被作为一种设计模式。
1.当逻辑简单时,使用简单工厂
2.当逻辑复杂,使用工厂模式
3.在2的前提下,产品等级结构确定时,使用抽象工厂模式。