工厂模式是一种创建型设计模式,用于处理对象的创建,以便代码结构更加清晰。简单工厂模式是工厂模式的一种形式,它提供了一个集中的工厂类来创建不同类型的对象。
1、简单工厂模式
- 工厂类(Factory Class):负责创建对象的类,包含一个工厂方法。
- 产品接口(Product Interface):定义了产品的公共接口。
- 具体产品类(Concrete Product Classes):实现了产品接口的具体类。
- 客户端(Client):使用工厂类来创建产品对象。
例如一个电视的工厂模式:
cpp
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
class TV
{
public:
virtual void display() = 0;
};
class TclTV
: public TV
{
public:
void display() override
{
cout << "this is a Tcl TV" << endl;
}
};
class SonyTV
: public TV
{
public:
void display() override
{
cout << "this is a Sony TV" << endl;
}
};
class XiaoMiTV
: public TV
{
public:
void display() override
{
cout << "this is a XiaoMi TV" << endl;
}
};
class Factory
{
public:
static TV *create(string TVtype)
{
if (TVtype == "TLC")
{
return new TclTV();
}
else if (TVtype == "Sony")
{
return new SonyTV();
}
else if (TVtype == "XiaoMi")
{
return new XiaoMiTV();
}
else
{
return nullptr;
}
}
};
int main()
{
TV *pTV = Factory::create("Sony");
pTV->display();
return 0;
}
优点:
- 可以根据名字生产产品结构简单
缺点:
- 违反了单一职责原则
- 违反了开放闭合原则
- 违反了依赖导致原则
ps:
单一职责原则:一个类应该只有一个职责,并且该职责应该被封装在该类中。所有与该职责相关的工作都应该由这个类来完成,而与该职责无关的工作应该被分离出去,放到其他类中。
开放闭合原则:软件实体应该是可扩展的,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。
依赖导致原则:依赖倒置原则鼓励开发者通过接口或抽象类来定义对象之间的依赖关系,而不是直接依赖于具体的实现类。
2、工厂模式
弥补简单工厂的缺点,将工厂泛化使其遵循单一职责原则,开放闭合原则,依赖倒置原则。
cpp
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
class TV
{
public:
virtual void display() = 0;
};
class TclTV
: public TV
{
public:
void display() override
{
cout << "this is a Tcl TV" << endl;
}
};
class SonyTV
: public TV
{
public:
void display() override
{
cout << "this is a Sony TV" << endl;
}
};
class XiaoMiTV
: public TV
{
public:
void display() override
{
cout << "this is a XiaoMi TV" << endl;
}
};
class Factory
{
public:
virtual TV *create();
};
class TclFactory
: public Factory
{
public:
TV *create() override
{
return new TclTV();
}
};
class XiaoMiFactory
: public Factory
{
public:
TV *create() override
{
return new XiaoMiTV();
}
};
class SonyFactory
: public Factory
{
public:
TV *create() override
{
return new SonyTV();
}
};
int main()
{
SonyFactory sf;
TV *pTV = sf.create();
pTV->display();
return 0;
}
优点:
- 符合设计模式要求,可拓展性强
缺点:
- 一个类对应一个工厂,如果类很多,就需要太多的工厂,代码很繁琐。
3、抽象工厂模式
抽象工厂模式中的"产品族"指的是由同一个工厂生产的、位于不同产品等级结构中的一组产品。产品族中的产品虽然处于不同的产品等级结构中,但它们之间存在一定的关联性,通常属于同一类产品或具有相似的功能。例如,在家用电器的场景中,一个电器品牌(如美的或格力)下的所有产品(如冰箱、空调)可以构成一个产品族。
组件:
-
抽象产品(Abstract Product):
Phone
和Computer
是抽象产品,它们定义了产品对象的接口。
-
具体产品(Concrete Product):
XiaoMiPhone
、HuaWeiPhone
、XiaoMicomputer
和HuaWeiComputer
是具体产品,它们实现了抽象产品接口,并由具体的工厂类实例化。
-
抽象工厂(Abstract Factory):
Factory
是抽象工厂,它声明了一组用于创建抽象产品的方法。
-
具体工厂(Concrete Factory):
XiaoMiFactory
和HuaWeiFactory
是具体工厂,它们实现了抽象工厂的接口,并提供了创建具体产品的方法。
-
客户端(Client):
- 客户端代码使用抽象工厂来创建产品,而不需要知道具体的产品类。客户端通常通过抽象工厂的接口与产品交互。
cpp
#include <iostream>
using std::cout;
using std::endl;
class Phone
{
public:
virtual void show() = 0;
virtual ~Phone();
};
class XiaoMiPhone : public Phone
{
public:
void show() override
{
cout << "XiaoMiPhone" << endl;
}
};
class HuaWeiPhone : public Phone
{
public:
void show() override{
cout<<"HuaWeiPhone"<<endl;
}
};
class Computer{
public:
virtual void show()=0;
virtual ~Computer();
};
class XiaoMicomputer : public Computer
{
public:
void show() override
{
cout << "XiaoMicomputer" << endl;
}
};
class HuaWeiComputer : public Computer
{
public:
void show() override{
cout<<"HuaWeiComputer"<<endl;
}
};
class Factory{
public:
virtual Phone* createPhone()=0;
virtual Computer* createComputer()=0;
};
class XiaoMiFactory:public Factory{
public:
Phone* createPhone() override{
return new XiaoMiPhone();
}
Computer* createComputer() override{
return new XiaoMicomputer();
}
};
class HuaWeiFactory:public Factory{
public:
Phone* createPhone() override{
return new HuaWeiPhone();
}
Computer* createComputer() override{
return new HuaWeiComputer();
}
};
优点:
- 解耦:客户端不需要知道具体的产品类,只需要知道抽象产品。
- 扩展性 :添加新产品时,只需要添加一个新的具体工厂和具体产品类,无需修改现有代码。
- 封装性:具体的创建逻辑被封装在工厂类中,客户端不需要了解对象是如何被创建和组装的。
缺点:
- 产品族的扩展 :如果需要添加新的产品族,需要修改抽象工厂接口,这可能会导致需要修改所有具体的工厂类。
- 产品等级结构的固定:抽象工厂模式假设所有产品都具有相同的等级结构,如果产品之间存在不同的等级结构,这种模式可能不适用。
与普通工厂模式相比,抽象工厂模式不用对每一个产品设置一个工厂,减少了工厂数量,但也多个许多限制。
4、适用场景
-
简单工厂模式:
- 当创建对象不需要多种工厂类时,可以使用简单工厂模式。它适用于系统可能只需要一个工厂类,或者根据参数返回不同类的实例的情形。
- 适用于创建对象的过程比较简单,不需要复杂的逻辑判断,或者创建对象的代码可以被封装在一个单独的方法中。
- 当系统可能只有一个工厂类,或者根据参数的不同返回不同类的实例时,适合使用简单工厂模式。
-
工厂方法模式:
- 当创建对象需要使用大量重复的代码时,或者客户端不依赖于产品类,不关心实例是如何被创建和实现等细节时,适合使用工厂方法模式。
- 当一个类通过其子类来指定创建哪个对象时,工厂方法模式可以提供更好的灵活性和扩展性。
- 适用于客户端只知道创建产品的工厂名,而不知道具体的产品名,或者创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
-
抽象工厂模式:
- 当需要创建一系列相关或相互依赖的对象时,适合使用抽象工厂模式。
- 当客户端不关心产品实例如何被创建、实现等细节,而是强调一系列相关的产品对象(属于同一产品族)一起使用时,抽象工厂模式是合适的选择。
- 提供一个产品类库,所有的产品以同样的接口出现,使客户端不依赖于具体实现时,抽象工厂模式可以提供更好的封装和解耦。