【设计模式学习笔记】简单工厂模式、工厂模式、抽象工厂模式案例详解(C++实现)
目录
一、简单工厂模式
1. 什么是简单工厂模式
Simple Factory Pattern,简单工厂模式,也叫做静态工厂方法模式(Static Factory Method Pattern)。属于类的创建型设计模式的一种,通过一个专门的类(工厂)来负责创建其他类的实例(具体产品),这些类都有一个共同的抽象类作为基类(抽象产品)。
简单工厂模式中的三个角色
- 工厂角色:Creator,用于创建所有的具体产品实例,是简单工厂模式的核心。工厂类直接被外部调用,并提供一个静态方法,根据传入的参数不同来创建不同产品类的实例。
- 抽象产品角色:Product,它是工厂类所创建的所有实例的类的共同基类,用于描述产品的公共接口。它和工厂类是依赖的关系(作为工厂类静态方法的返回值)。
- 具体产品角色:Concrete Product,它是抽象产品类的子类,也是工厂类要创建的目标类。
2. 简单工厂模式实例
假设我们要生产一个手机,由苹果手机,小米手机,首先我们应该定义一个抽象产品类PhoneInterface
//抽象产品类
class PhoneInterface
{
public:
virtual void print_brand() = 0;
};
然后根据抽象产品类来实现具体的产品类,假设我们有苹果手机和小米手机
//具体产品类
class apple : public PhoneInterface
{
public:
virtual void print_brand()
{
cout << "苹果手机" << endl;
}
};
class XiaoMi : public PhoneInterface
{
public:
virtual void print_brand()
{
cout << "小米手机" << endl;
}
};
接下来就应该创建一个工厂类,在工厂类中定义了创建所有产品类实例的逻辑,以及选择创建哪个产品类实例的判断。
//工厂类
class Factory
{
public:
PhoneInterface* production_phone(int flag)
{
PhoneInterface* pTemp = NULL;
switch (flag) //所有的生产都集中在一个工厂中,每次修改都要在类中修改,不符合开闭原则
{
case 1:
pTemp = new apple;
break;
case 2:
pTemp = new XiaoMi;
break;
default:
pTemp = NULL;
break;
}
return pTemp;
}
};
这样,客户就可以通过工厂类来生产客户所需要的手机,并可以成功完成手机型号的生产。
int main()
{
Factory* pF = NULL;
PhoneInterface* pPhone = NULL;
pF = new Factory;
pPhone = pF->production_phone(1);
pPhone->print_brand();
delete pPhone;
pPhone = pF->production_phone(2);
pPhone->print_brand();
delete pF;
delete pPhone;
system("pause");
return 0;
}
3. 简单工厂模式的优缺点
优点:工厂类是整个简单工厂模式的核心,通过工厂类对外隐藏了创建实例的具体细节,用户直接使用工厂类去创建自己需要的实例,而不必关心实例是如何创建出来的,也不必关心内部结构是怎么组织的。
缺点:正所谓成也萧何,败也萧何,简单工厂模式的优点来源于工厂类,其缺点也来源于工厂类,因为所有实例的创建逻辑都集中在工厂类中,一旦工厂出现问题,所有实例的创建都将无法进行,并且增删产品都要去修改工厂类来实现,不符合开闭原则。因为简单工厂模式不符合开闭原则,所以它不是标准的设计模式。
二、工厂模式
1. 什么是工厂模式
factory pattern,工厂模式同样属于类的创建型模式,也成为多态工厂模式。工厂模式对简单工厂模式不遵守开闭原则这一缺点做了修正,工厂模式多出了一个抽象工厂角色作为接口,实际的生产工作在具体工厂类中实现,这样进一步的抽象化使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。简单来说,就是把简单工厂中的工厂细分为不同产品的工厂,每个工厂生产一种产品。
- 抽象工厂角色(Creator),所有具体工厂都要实现这个接口;
- 具体工厂(Concrete Creator),负责实例化具体产品对象;
- 抽象角色(Product),和简单工厂模式一样,它是工厂类所创建的所有实例的类的共同基类,用于描述产品的公共接口。
- 具体产品角色(Concrete Product),具体工厂类所要实例化的对象。
2. 工厂模式实例
抽象产品类和具体产品类不变
//抽象产品类
class PhoneInterface
{
public:
virtual void print_brand() = 0;
};
//苹果手机产品实现
class apple : public PhoneInterface
{
public:
virtual void print_brand()
{
cout << "苹果手机" << endl;
}
};
//小米手机产品实现
class XiaoMi : public PhoneInterface
{
public:
virtual void print_brand()
{
cout << "小米手机" << endl;
}
};
首先定义一个抽象的工厂类,来定义具体工厂的统一接口
//抽象工厂类
class FactoryInterface
{
public:
virtual PhoneInterface* production_phone() = 0;
};
然后定义一个苹果手机工厂,用于生产苹果手机,再定义一个小米手机工厂,用于生产苹果手机,那么这两个工厂就是具体工厂角色
//苹果手机工厂
class AppleFactory : public FactoryInterface
{
public:
virtual PhoneInterface* production_phone()
{
return new apple;
}
};
//小米手机工厂
class XiaomiFactory : public FactoryInterface
{
public:
virtual PhoneInterface* production_phone()
{
return new XiaoMi;
}
};
当我们需要生产手机产品的时候,直接使用苹果手机工厂去创建苹果手机对象,用小米手机工厂去创建小米手机对象即可。假如,我们增加需求,需要华为手机,这时只要增加一个华为工厂和华为手机的实现类即可,工厂的抽象类和手机的抽象类都不用动,符合开闭原则。
int main()
{
FactoryInterface* pFactory = NULL;
PhoneInterface* pPhone = NULL;
//要生产一台苹果手机
//先创建一个苹果手机工厂
pFactory = new AppleFactory;
pPhone = pFactory->production_phone();
pPhone->print_brand();
delete pPhone;
delete pFactory;
//生产一个小米手机
pFactory = new XiaomiFactory;
pPhone = pFactory->production_phone();
pPhone->print_brand();
delete pPhone;
delete pFactory;
system("pause");
return 0;
}
3. 简单工厂与工厂模式对比
简单工厂模式把所有的创建逻辑都放在了一个工厂类中,而工厂模式则是提供了一个抽象的工厂接口,由具体工厂去创建产品实例,极大的方便了增加产品,删除产品等操作,且很好的符合了开闭原则,简单工厂模式每次增删产品都要直接修改工厂类,而工厂模式只需要增加一个具体工厂类和一个具体产品类就可以完成功能的扩充。
在简单工厂模式中,客户端是面向具体工厂编程,增加产品要在工厂类中修改代码;而工厂模式是面向抽象工厂编程,增加产品只要创建一个新的具体工厂就可以了,这就是面向抽象类编程。
三、抽象工厂模式
1. 什么是抽象工厂模式
Abstract Factory Pattern,抽象工厂模式。假设在前面的工厂模式下,我们对产品线提出了进一步的要求,因为手机既要在国内销售,又要在国外销售,所以同一品牌手机增加了大陆版、美版、港版等产品线。如果使用工厂模式,每一个品牌的手机,每一个版本的手机都要单独一个具体工厂来创建,很不方便‘这时候,就有了抽象工厂模式,抽象工厂模式可以创建一个产品族(包含多条产品线)。抽象工厂模式用官方语言描述就是,一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。 她也有四种角色,和工厂模式一样。
- 抽象工厂角色(Creator),所有具体工厂都要实现这个接口,可以创建多个不同等级的产品(多条产品线);
- 具体工厂(Concrete Creator),负责实例化具体产品对象,多条产品线;
- 抽象角色(Product),和简单工厂模式一样,它是工厂类所创建的所有实例的类的共同基类,用于描述产品的公共接口。
- 具体产品角色(Concrete Product),具体工厂类所要实例化的对象。
2. 抽象工厂模式实例
首先创建一个抽象手机类
//抽象产品
class PhoneInterface
{
public:
virtual void print_brand() = 0;
};
根据抽象手机类定义大陆版苹果手机类,美版苹果手机类,大陆版小米手机类,美版小米手机类
//美版的苹果手机
class UsApple : public PhoneInterface
{
public:
virtual void print_brand()
{
cout << "美版的苹果手机" << endl;
}
};
//大陆版小米手机
class ChinaXiaomi : public PhoneInterface
{
public:
virtual void print_brand()
{
cout << "大陆版本的小米手机" << endl;
}
};
//美版的小米手机
class UsXiaomi : public PhoneInterface
{
public:
virtual void print_brand()
{
cout << "美版的小米手机" << endl;
}
};
接下来定义一个抽象工厂类,该抽象工厂类中包含两个接口,一个是苹果手机生产线,一个是小米手机生产线
//抽象工厂
class FactoryInterface
{
public:
//产品线1:苹果手机
virtual PhoneInterface* production_apple() = 0;
//产品线2:小米手机
virtual PhoneInterface* production_xiaomi() = 0;
};
根据抽象工厂来定义两个具体工厂,一个是大陆版手机工厂,一个是美版手机工厂
//生产大陆版本手机的工厂
class ChinaFactory : public FactoryInterface
{
public:
//产品线1:苹果手机
virtual PhoneInterface* production_apple()
{
return new ChinaApple;
}
//产品线2:小米手机
virtual PhoneInterface* production_xiaomi()
{
return new ChinaXiaomi;
}
};
//生产美版手机的工厂
class UsFactory : public FactoryInterface
{
public:
//产品线1:苹果手机
virtual PhoneInterface* production_apple()
{
return new UsApple;
}
//产品线2:小米手机
virtual PhoneInterface* production_xiaomi()
{
return new UsXiaomi;
}
};
客户可以直接使用两个具体工厂去生产大陆版苹果/小米手机或美版苹果/小米手机
int main()
{
FactoryInterface* pFactory = NULL;
PhoneInterface* pPhone = NULL;
//使用大陆版手机的工厂
cout << "======大陆版手机工厂======" << endl;
pFactory = new ChinaFactory;
//生产大陆版苹果手机
pPhone = pFactory->production_apple();
pPhone->print_brand();
delete pPhone;
//生产大陆版小米手机
pPhone = pFactory->production_xiaomi();
pPhone->print_brand();
delete pPhone;
delete pFactory;
//使用美版手机的工厂
cout << "======美版手机工厂======" << endl;
pFactory = new UsFactory;
pPhone = pFactory->production_apple();
pPhone->print_brand();
delete pPhone;
pPhone = pFactory->production_xiaomi();
pPhone->print_brand();
delete pPhone;
delete pFactory;
system("pause");
return 0;
}
3. 抽象工厂类总结
当增加一个新的产品族时,只需要增加一个新的具体工厂即可,如果整个产品族只有一个等级的产品,比如只有一条生产线,抽象工厂就和工厂模式一样了。