六⼤原则
类的职责应该单⼀,⼀个⽅法只做⼀件事,职责划分清晰了
对扩展开放,对修改封闭对软件实体的改动,最好⽤扩展⽽⾮修改的⽅式。
通俗点讲,就是只要⽗类能出现的地⽅,⼦类就可以出现,⽽且替换为⼦类也不会产⽣任何错误或异常。在继承类时,务必重写⽗类中所有的⽅法,尤其需要注意⽗类的protected⽅法,⼦类尽量不要暴露⾃⼰的public⽅法供外界调⽤。
⾼层模块不应该依赖低层模块,两者都应该依赖其抽象. 不可分割的原⼦逻辑就是低层模式,原⼦逻辑组装成的就是⾼层模块。模块间依赖通过抽象(接⼝)发⽣,具体类之间不直接依赖
尽量减少对象之间的交互,从⽽减⼩类之间的耦合。⼀个对象应该对其他对象有最少的了解。
客⼾端不应该依赖它不需要的接⼝,类间的依赖关系应该建⽴在最⼩的接⼝上使⽤建议:接⼝设计尽量精简单⼀,但是不要对外暴露没有实际意义的接⼝。⽤例:修改密码,不应该提供修改⽤⼾信息接⼝,⽽就是单⼀的最⼩修改密码接⼝,更不要暴露数据库操作
从整体上来理解六⼤设计原则,可以简要的概括为⼀句话,⽤抽象构建框架,⽤实现扩展细节,具体 到每⼀条设计原则,则对应⼀条注意事项:
单⼀职责原则告诉我们实现类要职责单⼀;⾥⽒替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要⾯向接⼝编程;接⼝隔离原则告诉我们在设计接⼝的时候要精简单⼀;迪⽶特法则告诉我们要降低耦合;开闭原则是总纲,告诉我们要对扩展开放,对修改关闭。
单例模式
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个
访问它的全局访问点,该实例被所有程序模块共享。
比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
单例模式有两种实现模式:饿汉模式,懒汉模式
饿汉模式
就是说不管你将来用不用,程序启动时就会创建⼀个唯⼀的实例对象。 因为单例对象已经确定, 所以⽐较适⽤于多线程环境中, 多线程获取单例对象不需要加锁, 可以有效的避免资源竞争, 提⾼性能。
#include <iostream>
using namespace std;
class Singleton {
private:
static Singleton _eton;
int _data;
private:
Singleton() :_data(99) {
cout << "单例对象构造" << endl;
}
~Singleton() {}
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton& getInstance()
{
return _eton;
}
int getData() {
return _data;
}
};
Singleton Singleton::_eton;
int main()
{
//cout << Singleton::getInstance().getData() << endl;
return 0;
}
结果演示
注释前:
注释后:
由此可见,在main函数启动后,就会自动构造单例对象,即便是没有调用该单例对象。
懒汉模式
第⼀次使⽤要使⽤单例对象的时候创建实例对象。如果单例对象构造特别耗时或者耗费资源(加载插件、加载⽹络资源等), 可以选择懒汉模式, 在第⼀次使⽤的时候才创建对象。
class B
{
public:
static B* GetInstance()
{
if (_inst == nullptr)
{
_inst = new B;
}
return _inst;
}
static void DelInstance()
{
if (_inst)
{
delete _inst;
_inst = nullptr;
}
}
private:
B()
{}
~B()
{
cout << "数据写到文件" << endl;
}
B(const B& aa) = delete;
B& operator=(const B& aa) = delete;
static B* _inst;
class gc
{
public:
~gc()
{
DelInstance();
}
};
static gc _gc;
};
B* B::_inst = nullptr;
B::gc B::_gc;
下面再介绍一种《Effective C++》⼀书作者 Scott Meyers 提出的⼀种更加优雅简便的单例模式 Meyers' Singleton in C++。
C++11 Static local variables 特性以确保C++11起,静态变量将能够在满⾜ thread-safe 的前提下唯⼀地被构造和析构。
#include <iostream>
using namespace std;
class Singleton {
private:
int _data;
private:
Singleton() :_data(99) {
cout << "单例对象构造" << endl;
}
~Singleton() {}
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton& getInstance()
{
static Singleton _eton;
return _eton;
}
int getData() {
return _data;
}
};
int main()
{
cout << Singleton::getInstance().getData() << endl;
return 0;
}
结果演示
没注释:
注释后:
由此可见,懒汉模式中,只有第一次创建对象时,才会构造单例对象。
工厂模式
简单工厂模式
简单⼯⼚模式:通过参数控制可以⽣产任何产品
优点:简单粗暴,直观易懂。使⽤⼀个⼯⼚⽣产同⼀等级结构下的任意产品
缺点:
1. 所有东西⽣产在⼀起,产品太多会导致代码量庞⼤
2. 开闭原则遵循(开放拓展,关闭修改)的不是太好,要新增产品就必须修改⼯⼚⽅法。
#include <iostream>
#include <string>
#include <memory>
class Fruit {
public:
Fruit() {}
virtual void show() = 0;
};
class Apple : public Fruit {
public:
Apple() {}
virtual void show() {
std::cout << "我是一个苹果" << std::endl;
}
};
class Banana : public Fruit {
public:
Banana() {}
virtual void show() {
std::cout << "我是一个香蕉" << std::endl;
}
};
class FruitFactory {
public:
static std::shared_ptr<Fruit> create(const std::string& name) {
if (name == "苹果") {
return std::make_shared<Apple>();
}
else if (name == "⾹蕉") {
return std::make_shared<Banana>();
}
return std::shared_ptr<Fruit>();
}
};
int main()
{
std::shared_ptr<Fruit> fruit = FruitFactory::create("苹果");
fruit->show();
fruit = FruitFactory::create("⾹蕉");
fruit->show();
return 0;
}
工厂方法模式
⼯⼚⽅法:定义⼀个创建对象的接⼝,但是由⼦类来决定创建哪种对象,使⽤多个⼯⼚分别⽣产指定的固定产品
优点:
1. 减轻了⼯⼚类的负担,将某类产品的⽣产交给指定的⼯⼚来进⾏
2. 开闭原则遵循较好,添加新产品只需要新增产品的⼯⼚即可,不需要修改原先的⼯⼚类
缺点:对于某种可以形成⼀组产品族的情况处理较为复杂,需要创建⼤量的⼯⼚类.
#include <iostream>
#include <string>
#include <memory>
class Fruit {
public:
Fruit() {}
virtual void show() = 0;
};
class Apple : public Fruit {
public:
Apple() {}
virtual void show() {
std::cout << "我是一个苹果" << std::endl;
}
private:
std::string _color;
};
class Banana : public Fruit {
public:
Banana() {}
virtual void show() {
std::cout << "我是一个香蕉" << std::endl;
}
};
class FruitFactory {
public:
virtual std::shared_ptr<Fruit> create() = 0;
};
class AppleFactory : public FruitFactory {
public:
virtual std::shared_ptr<Fruit> create() {
return std::make_shared<Apple>();
}
};
class BananaFactory : public FruitFactory {
public:
virtual std::shared_ptr<Fruit> create() {
return std::make_shared<Banana>();
}
};
int main()
{
std::shared_ptr<FruitFactory> factory(new AppleFactory());
std::shared_ptr<Fruit> fruit = factory->create();
fruit->show();
factory.reset(new BananaFactory());
fruit = factory->create();
fruit->show();
return 0;
}
运行结果:
抽象工厂模式
抽象⼯⼚:围绕⼀个超级⼯⼚创建其他⼯⼚。每个⽣成的⼯⼚按照⼯⼚模式提供对象。
思想:将⼯⼚抽象成两层,抽象⼯⼚ & 具体⼯⼚⼦类, 在⼯⼚⼦类种⽣产不同类型的⼦产品
#include <iostream>
#include <string>
#include <memory>
class Fruit {
public:
Fruit() {}
virtual void show() = 0;
};
class Apple : public Fruit {
public:
Apple() {}
virtual void show() {
std::cout << "我是一个苹果" << std::endl;
}
private:
std::string _color;
};
class Banana : public Fruit {
public:
Banana() {}
virtual void show() {
std::cout << "我是一个香蕉" << std::endl;
}
};
class Animal {
public:
virtual void voice() = 0;
};
class Lamp : public Animal {
public:
void voice() { std::cout << "咩咩咩\n"; }
};
class Dog : public Animal {
public:
void voice() { std::cout << "汪汪汪\n"; }
};
class Factory {
public:
virtual std::shared_ptr<Fruit> getFruit(const std::string& name) = 0;
virtual std::shared_ptr<Animal> getAnimal(const std::string& name) = 0;
};
class FruitFactory : public Factory {
public:
virtual std::shared_ptr<Animal> getAnimal(const std::string& name) {
return std::shared_ptr<Animal>();
}
virtual std::shared_ptr<Fruit> getFruit(const std::string& name) {
if (name == "苹果") {
return std::make_shared<Apple>();
}
else if (name == "⾹蕉") {
return std::make_shared<Banana>();
}
return std::shared_ptr<Fruit>();
}
};
class AnimalFactory : public Factory {
public:
virtual std::shared_ptr<Fruit> getFruit(const std::string& name) {
return std::shared_ptr<Fruit>();
}
virtual std::shared_ptr<Animal> getAnimal(const std::string& name) {
if (name == "⼩⽺") {
return std::make_shared<Lamp>();
}
else if (name == "⼩狗") {
return std::make_shared<Dog>();
}
return std::shared_ptr<Animal>();
}
};
class FactoryProducer {
public:
static std::shared_ptr<Factory> getFactory(const std::string& name) {
if (name == "动物") {
return std::make_shared<AnimalFactory>();
}
else {
return std::make_shared<FruitFactory>();
}
}
};
int main()
{
std::shared_ptr<Factory> fruit_factory = FactoryProducer::getFactory("⽔果");
std::shared_ptr<Fruit> fruit = fruit_factory->getFruit("苹果");
fruit->show();
fruit = fruit_factory->getFruit("⾹蕉");
fruit->show();
std::shared_ptr<Factory> animal_factory = FactoryProducer::getFactory("动物");
std::shared_ptr<Animal> animal = animal_factory->getAnimal("⼩⽺");
animal->voice();
animal = animal_factory->getAnimal("⼩狗");
animal->voice();
return 0;
}
运行结果:
建造者模式
抽象产品类:具体产品类:⼀个具体的产品对象类抽象Builder类:创建⼀个产品对象所需的各个部件的抽象接⼝具体产品的Builder类:实现抽象接⼝,构建各个部件指挥者Director类:统⼀组建过程,提供给调⽤者使⽤,通过指挥者来构造产品
#include <iostream>
#include <memory>
/*抽象电脑类*/
class Computer {
public:
Computer() {}
void setBoard(const std::string& board) { _board = board; }
void setDisplay(const std::string& display) { _display = display; }
virtual void setOs() = 0;
std::string toString() {
std::string computer = "Computer:{\n";
computer += "\tboard=" + _board + ",\n";
computer += "\tdisplay=" + _display + ",\n";
computer += "\tOs=" + _os + ",\n";
computer += "}\n";
return computer;
}
protected:
std::string _board;
std::string _display;
std::string _os;
};
/*具体产品类*/
class MacBook : public Computer {
public:
MacBook() {}
virtual void setOs() {
_os = "Max Os X12";
}
};
/*抽象建造者类:包含创建⼀个产品对象的各个部件的抽象接⼝*/
class Builder {
public:
virtual void buildBoard(const std::string& board) = 0;
virtual void buildDisplay(const std::string& display) = 0;
virtual void buildOs() = 0;
virtual std::shared_ptr<Computer> build() = 0;
};
/*具体产品的具体建造者类:实现抽象接⼝,构建和组装各个部件*/
class MacBookBuilder : public Builder {
public:
MacBookBuilder() : _computer(new MacBook()) {}
virtual void buildBoard(const std::string& board) {
_computer->setBoard(board);
}
virtual void buildDisplay(const std::string& display) {
_computer->setDisplay(display);
}
virtual void buildOs() {
_computer->setOs();
}
virtual std::shared_ptr<Computer> build() {
return _computer;
}
private:
std::shared_ptr<Computer> _computer;
};
/*指挥者类,提供给调⽤者使⽤,通过指挥者来构造复杂产品*/
class Director {
public:
Director(Builder* builder) :_builder(builder) {}
void construct(const std::string& board, const std::string& display) {
_builder->buildBoard(board);
_builder->buildDisplay(display);
_builder->buildOs();
}
private:
std::shared_ptr<Builder> _builder;
};
int main()
{
Builder* buidler = new MacBookBuilder();
std::unique_ptr<Director> pd(new Director(buidler));
pd->construct("英特尔主板", "VOC显示器");
std::shared_ptr<Computer> computer = buidler->build();
std::cout << computer->toString();
return 0;
}
运行结果:
代理模式
静态代理指的是,在编译时就已经确定好了代理类和被代理类的关系。也就是说,在编译时就已经确定了代理类要代理的是哪个被代理类。动态代理指的是,在运⾏时才动态⽣成代理类,并将其与被代理类绑定。这意味着,在运⾏时才能确定代理类要代理的是哪个被代理类。
/*房东要把⼀个房⼦通过中介租出去理解代理模式*/
#include <iostream>
#include <string>
class RentHouse {
public:
virtual void rentHouse() = 0;
};
/*房东类:将房⼦租出去*/
class Landlord : public RentHouse {
public:
void rentHouse() {
std::cout << "将房子租出去\n";
}
};
/*中介代理类:对租房⼦进⾏功能加强,实现租房以外的其他功能*/
class Intermediary : public RentHouse {
public:
void rentHouse() {
std::cout << "发布招租启示\n";
std::cout << "带人看房\n";
_landlord.rentHouse();
std::cout << "负责租后维修\n";
}
private:
Landlord _landlord;
};
int main()
{
Intermediary intermediary;
intermediary.rentHouse();
return 0;
}
运行结果: