六大设计原则
1)单一职责原则
类的职责单一,对外提供一个功能,函数也支持;
2)里氏替换原则
任何抽象类的出现都可以用他的实现类进行替换。
3)依赖倒置原则
依赖于抽象,不要依赖具体实现,也就是针对接口编程
4)接口隔离原则
一个接口对外应该只提供一种对外功能,不应该把所有操作都封装到一个接口里。
5)开闭原则
对扩展开放,对修改关闭;
//代码实现
class AbstractCaculator{
public:virtual int getResult() = 0;virtual void setOperatorNumber(int a,int b) = 0;
};
//加法计算器类
class PlusCaculator : public AbstractCaculator{
public:virtual void setOperatorNumber(int a,int b){this->mA = a;this->mB = b;
}
virtual int getResult(){return mA + mB;
}
public:int mA;int mB;
};
//减法计算器类
class MinuteCaculator : public AbstractCaculator{
public:virtual void setOperatorNumber(int a,int b){this->mA = a;this->mB = b;
}
virtual int getResult(){return mA - mB;
}
public:int mA;int mB;
};
//调用
void test(){AbstractCaculator* caculator1 = new PlusCaculator;caculator1->setOperatorNumber(10,20);caculator1->getResult();//30AbstractCaculator* caculator2 = new MinuteCaculator;caculator2->setOperatorNumber(30,20);caculator2->getResult();//10
}
6)迪米特原则(最少知识原则)
对象之间应该尽可能降低耦合度,可以通过提供一个
统一的接口来实现对象之间的交互
常见的设计模式
1)单例模式
单例模式,顾名思义,就是一个类只能有一个对象。
单例模式如何实现?
1)构造函数或者拷贝构造函数私有化;
2)共有的静态变量和静态函数;
单例模式分为懒汉模式和饿汉模式。懒汉模式是在第一次用到类实例时才会实例化对象,而饿汉模式在定义时就创建了对象。其中,在多线程情况下,懒汉模式需要考虑安全问题,而饿汉模式不需要。
懒汉模式代码如下:
class Singleton
{
private:Singleton(); // 构造函数私有化Singleton(const Singleton& other); // 拷贝构造函数私有化
public:static Singleton* getInstance();// 静态成员函数static Singleton* m_instance;// 静态变量
};
Singleton* Singleton::m_instance = nullptr;
//线程非安全版本
Singleton* Singleton::getInstance()
{if(m_instance == nullptr){m_instance = new Singleton();}return m_instance;
}
//线程安全版本,加锁,但锁的成本太高(读操作是不必加锁的;高并发)
Singleton* Singleton::getInstance()
{Lock lock;if(m_instance == nullptr){m_instance = new Singleton();}return m_instance;
}
//双检查锁,但由于内存读写reorder不安全
Singleton* Singleton::getInstance()
{if(m_instance == nullptr){Lock lock;if(m_instance == nullptr){m_instance = new Singleton();}}return m_instance;
}
注意:先分配内存,再调用构造器,最后内存赋值给m_instance,reorder之后可能会发生先分配内存,再内存赋值给m_instance,最后调用构造器。
// C++ 11 版本之后的跨平台实现(volatile)
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;Singleton* Singleton::getInstance()
{Singleton* temp = m_instance.load(std::memory_order_relaxed);std::atomic_thread_fence(std::memory_order_acquire);//获取内存fenceif(temp == nullptr){std::lock_guard<std::mutex> lock(m_mutex);if(temp == nullptr){temp = new Singleton;std::atomic_thread_fence(std::memory_order_relaxed);m_instance.store(temp, std::memory_order_relaxed);}}return temp;
}
线程安全的饿汉模式
2)策略模式【策略模式适用于实现某一功能,而实现该功能的算法是经常改变的情况】
当存在以下情况时使用Strategy模式:
1)许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法;
2)需要使用一个算法的不同变体;
3)算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构;
4)一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以替代这些条件语句。
//代码实现
3)外观模式【肯德基套餐模式】
将复杂的子系统抽象到一个接口中管理,外界只需要通过该接口实现与子系统进行交互,而不必直接与子系统进行交互。
4)简单工厂模式
5)工厂模式
工厂模式=简单工厂模式+开闭原则
缺点:类的个数成倍增加,导致类越来越多,代码维护量加大。
6)抽象工厂模式
提供一个创建一系列相关或者互相依赖对象的接口,而无需指定具体的类;
主要解决接口选择的问题。
7)观察者模式
定义了一对多的关系,让多个观察者同时监听某一主题对象,当该主题对象发生变化时,将通知其他观察者对象。
观察者模式主要的角色,分别是:
抽象的观察者;具体的观察者;抽象的观察者目标;具体的观察者目标。
UML及设计文档内容模块