设计模式基本准则
1.单一职责原则 (Single Responsibility Principle)
一个类应该只有一个引起它变化的原因。每个类应该只负责一项职责,这样可以提高类的内聚性和可维护性。
2.开放封闭原则 (Open-Closed Principle)
软件实体(类、模块、函数等)应该对拓展开放,对修改关闭。通过使用抽象对象和接口,可以使系统在不修改现有代码的情况下进行扩展。
3.里氏替换原则 (Liskov SubStitution Principle)
子类应该能够替换其基类,而不会破坏系统的正确性。子类应该遵循基类的契约和行为。
4.依赖倒置原则 (Dependency Inversion Principle)
高层模块不应该依赖于底层模块,二者都不应该依赖于抽象。抽象应该依赖于细节,而不是细节依赖于抽象。
5.接口隔离原则 (Interface Segregation Principle)
客户端不应该依赖于它不需要的接口。接口应该小而专注,而不是大而笨重。
什么是工厂模式
工厂模式是一种常见的软件设计模式,它用于创建对象的实例。它通过提供一个通用的接口来封装对象的创建过程,以及在运行时决定实例化哪个具体的对象。工厂模式将对象的创建和使用分离,使代码更具可维护性、可扩展性和可测试性。
工厂模式通常涉及一个抽象工厂类或接口,该工厂类定义了创建对象的方法。具体的工厂类则实现了这个接口,并根据特定的需求进行对象的实例化。客户端代码只需通过工厂类的接口来创建对象,而无需直接与具体的类进行交互。
工厂模式有助于解耦对象的创建和使用,同时也提供了一种灵活的方式来创建不同类型的对象。它在许多应用中被广泛使用,例如在数据库访问、依赖注入、插件系统等方面。
为什么使用工厂模式
使用工厂模式有以下几个主要的优点和原因:
- 封装对象的创建逻辑
工厂模式将对象的创建过程封装在工厂类中,客户端只需要使用工厂类提供的接口来创建对象,而无需了解具体的创建逻辑。这样可以隐藏实例化的细节,降低了客户款的复杂性。
- 解耦对象的创建和应用
工厂模式将对象的创建和使用分离开来,使得客户端不依赖于具体的类,而只依赖于抽象的工厂接口。这种解耦可以降低代码的耦合度,提高代码的灵活性和可维护性。
- 可拓展性
工厂模式可以很方便的添加新的具体工厂类和产品类,从而实现在不修改客户端代码的情况下拓展系统功能。这种可拓展性对于需求频繁添加新类型对象的系统非常有用。
- 更好地代码复用
通过工厂模式,可以将对象的创建逻辑集中在工厂类中,避免了在多个地方重复创建相同的对象的代码。这样可以提高代码的复用性,减少了代码的冗余。
工厂模式实现步骤
1.定义抽象产品接口或类
创建一个抽象的产品接口或类,用于定义产品的共有属性和方法。
class Product{
public:
virtual void feature()=0;
};
2.创建具体产品类
实现抽象产品接口或类,定义具体产品的属性和方法。
class Pen:public Product{
public:
void feature() override {
printf("Pen的功能为写字。\n");
}
};
class Cup:public Product{
public:
void feature() override {
printf("Cup的功能为盛水。\n");
}
};
3.创建工厂类
实现工厂接口或类,根据具体的需求创建对象的实例。
class Factory{
public:
enum TYPE{TP_Pen,TP_Cup};
public:
static Product* createProduct(TYPE type) {
switch(type){
case TP_Pen:return new Pen();
case TP_Cup:return new Cup();
default:return nullptr;
}
}
}
4.在客户端代码中使用工厂类创建对象
在客户端代码中使用工厂类的接口来创建的对象,而不是直接实例化具体产品类。
int main() {
Product* pen = Factory::createProduct(Factory::TP_Pen);
pen->feature();
Product* cup = Factory::createProduct(Factory::TP_Cup);
cup->feature();
delete pen;
delete cup;
return 0;
}
工厂模式实现代码
#include <cstdio>
class Product{
public:
virtual void feature()=0;
};
class Pen:public Product{
public:
void feature() override {
printf("Pen的功能为写字。\n");
}
};
class Cup:public Product{
public:
void feature() override {
printf("Cup的功能为盛水。\n");
}
};
class Factory{
public:
enum TYPE{TP_Pen,TP_Cup};
public:
static Product* createProduct(TYPE type) {
switch(type){
case TP_Pen:return new Pen();
case TP_Cup:return new Cup();
default:return nullptr;
}
}
};
int main() {
Product* pen = Factory::createProduct(Factory::TP_Pen);
pen->feature();
Product* cup = Factory::createProduct(Factory::TP_Cup);
cup->feature();
delete pen;
delete cup;
return 0;
}
工厂模式优缺点
工厂模式的优点包括:
-
封装了对象的创建过程:工厂模式将对象的创建过程封装在工厂类中,客户端只需要通过工厂类来创建对象,而不需要直接调用具体产品类的构造函数。这样可以降低代码的耦合度,提高代码的可维护性和可扩展性。
-
隐藏了具体产品的实现细节:客户端只需要知道产品的抽象接口,而不需要了解具体产品的实现细节。这样可以提高系统的安全性和稳定性。
-
提供了灵活性和可扩展性:通过工厂类的扩展,可以方便地添加新的产品类,而不需要修改客户端的代码。这样可以提供更好的灵活性和可扩展性,适应系统需求的变化。
-
降低了客户端的复杂性:客户端只需要关注产品的接口和功能,而不需要关注产品的创建过程。这样可以降低客户端的复杂性,提高开发效率。
工厂模式的缺点包括:
-
增加了系统的复杂性:引入工厂类会增加系统的类和对象数量,增加了系统的复杂性。如果系统中只有少量的产品类,使用工厂模式可能会导致代码冗余。
-
增加了系统的抽象性:工厂模式通过引入抽象接口和抽象类,增加了系统的抽象性。这样可能会增加开发和理解的难度。
-
不易于理解和调试:工厂模式的代码结构相对复杂,不易于理解和调试。特别是在工厂类和产品类数量较多时,代码的可读性和可维护性会降低。
工厂模式在一些特定的场景下可以提供灵活性、可扩展性和代码复用性,但也需要权衡其引入带来的复杂性和抽象性。在设计系统时,需要根据具体的需求和情况来选择是否使用工厂模式。