单例模式
单例模式要求确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例(Ensure a class has only one instance, and provide a global point of access to it)
单例模式优点:
1.资源控制,确保全局只有一个实例对象,避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在 内存中,避免对同一个资源文件的同时写操作
2.能够进行全局状态管理,单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单 例类,负责所有数据表的映射处理
3.性能优化,能够减少对象创建开销,特别是一个对象需要频繁地 创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显
单例模式缺点:
1.违反单一职责原则,常常会职责过多,比如一个单例可以log,loadConfig等
2.测试困难,因为是单例在启动之前就初始化,所以一般使用初始化列表,所以很难使用依赖注入的方法,所以造成紧密耦合的依赖,比如使用的成员是实现类而不是抽象类(违反了依赖倒置的原则)
3.继承和扩展的局限性,无法通过继承创建多个实例
在设计模式中,接口通常通过纯虚类(abstract class)在C++中实现。接口定义了一组方法,但不涉及具体实现,单例模式通常不使用接口,原因如下:
自我实例化:单例类需要控制其实例化过程,确保只有一个实例。这通常通过私有构造函数和静态访问方法实现。如果引入接口,使用接口的代码需要通过接口指针或引用访问,这会破坏单例的全局访问点特性。
接口无意义:接口本身是抽象的,不能实例化。单例需要一个具体的类来管理唯一实例,接口无法直接支持这种需求。
由于单例类通常没有接口,扩展其功能较为困难。在需要扩展单例功能时,主要有以下几种方式:
修改现有代码:直接在单例类中添加新功能,需要修改类定义,影响所有使用该类的地方。
继承单例类(不推荐):虽然技术上可以通过继承扩展单例,但这会导致多个实例或破坏单例特性,通常不推荐。
工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类(Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.)
工厂方法模式是一种创建型设计模式,旨在提供一个用于创建对象的接口,而不暴露对象创建的具体逻辑。该模式通过将对象的实例化推迟到子类,使得系统能够在不修改现有代码的情况下增加新的产品
目的
封装对象创建:将对象创建过程封装在工厂类中,隐藏了具体实现细节。
提高灵活性:通过继承和多态,允许在不修改客户端代码的情况下扩展新产品。
降低耦合:客户端不再依赖具体类,只依赖抽象类型,提高了代码的灵活性和可维护性。
优点
单一职责:对象创建的职责由工厂类单独承担,符合单一职责原则。
符合开闭原则:对扩展开放,对修改封闭。增加新产品无需修改现有工厂类,只需新增具体工厂和产品类。
降低耦合:客户端与具体产品类解耦,依赖于抽象工厂和产品接口。
缺点
类的数量增加:每增加一种产品都需要相应的具体工厂类,可能导致系统中类的数量增多,增加复杂度。
使用复杂性:与简单的直接实例化相比,工厂方法的结构更复杂,适用于较为复杂的对象创建情境。
简单工厂模式
简单工厂模式并非标准的设计模式,但常被用来快速创建对象,它通过一个工厂类,根据传入的参数创建不同的产品实例
class SimpleButtonFactory{
public:
enum class ButtonType{Windows,Mac};
static std::unique_ptr<Button> createButton(ButtonType type){
switch(type){
case ButtonType::Windows:
return std::make_unique<WindowsButton>();
case ButtonType::Max:
return std::make_unique<MaxButton>();
default:
return nullptr;
}
}
};
抽象工厂模式
抽象工厂模式旨在创建一系列相关或相互依赖的对象,而不仅仅是一个产品,它提供一个接口,用于创建一组相关或依赖的对象,而无需指定具体类
class TextBox{
public:
virtual ~TextBox(){}
virtual std::string paint() const = 0;
};
class WindowsTextBox : public TextBox{
public:
std::string paint() const override {
return "Render a text box in a Windows style.";
}
}
class MacTextBox : public TextBox {
public:
std::string paint() const override {
return "Render a text box in a macOS style.";
}
};
class GUIFactory{
public:
virtual ~GUIFactory(){}
virtual std::unique_ptr<TextBox> createTextBox() const = 0;
};
class WindowsGUIFactory : public GUIFactory {
public:
std::unique_ptr<TextBox> createTextBox() const override {
return std::make_unique<WindowsTextBox>();
}
};
class MacGUIFactory : public GUIFactory {
public:
std::unique_ptr<TextBox> createTextBox() const override {
return std::make_unique<MacTextBox>();
}
};
建造者模式
建造者模式是一种创建型设计模式,旨在分步骤构建复杂对象,使得同一构建过程可以创建不同的表示。建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
具体来说,建造者模式通过将一个复杂对象的构建分解成多个简单的步骤,并允许通过不同的步骤创建不同的对象。模式中的主要角色:
1.Builder(抽象建造者):定义创建产品的各个部件的抽象方法
2.ConcreteBuilder(具体建造者):实现Builder接口,实现各个组件的具体构建,并提供获取最终产品的方法
3.Director(指挥者):负责安排建造者按照特定的顺序来构建产品
4.Product(产品):表示被构建的复杂对象,包含多个部件
class Car {
public:
void setEngine(const std::string& engine) {
this->engine = engine;
}
void setWheels(const std::string& wheels) {
this->wheels = wheels;
}
void setColor(const std::string& color) {
this->color = color;
}
private:
std::string engine;
std::string wheels;
std::string color;
};
class CarBuilder {
public:
virtual ~CarBuilder() = default;
virtual void buildEngine() = 0;
virtual void buildWheels() = 0;
virtual void buildColor() = 0;
std::unique_ptr<Car> getCar() {
return std::move(car);
}
protected:
std::unique_ptr<Car> car = std::make_unique<Car>();
};
class SportsCarBuilder :public CarBuilder {
public:
void buildEngine() override {
car->setEngine("V8 Engine");
}
void buildWheels() override {
car->setWheels("20-inch Alloy Wheels");
}
void buildColor() override {
car->setColor("Red");
}
};
class SUVCarBuilder : public CarBuilder {
public:
void buildEngine() override {
car->setEngine("V6 Engine");
}
void buildWheels() override {
car->setWheels("18-inch Steel Wheels");
}
void buildColor() override {
car->setColor("Black");
}
};
class CarDirecotr {
public:
void setBuilder(std::unique_ptr<CarBuilder> builder) {
builder = std::move(builder);
}
std::unique_ptr<Car> constructCar() {
if (builder) {
builder->buildEngine();
builder->buildWheels();
builder->buildColor();
return builder->getCar();
}
return nullptr;
}
private:
std::unique_ptr<CarBuilder> builder;
};
int main() {
CarDirector director;
// 构建一辆跑车
std::unique_ptr<CarBuilder> sportsCarBuilder = std::make_unique<SportsCarBuilder>();
director.setBuilder(std::move(sportsCarBuilder));
std::unique_ptr<Car> sportsCar = director.constructCar();
std::cout << "Sports Car:" << std::endl;
sportsCar->showSpecifications();
std::cout << std::endl;
// 构建一辆SUV
std::unique_ptr<CarBuilder> suvCarBuilder = std::make_unique<SUVCarBuilder>();
director.setBuilder(std::move(suvCarBuilder));
std::unique_ptr<Car> suvCar = director.constructCar();
std::cout << "SUV Car:" << std::endl;
suvCar->showSpecifications();
return 0;
}