- 什么是设计模式
指的是在特定环境下,人们解决某类重复出现问题的一套成功或有效的解决方案。
大白话是:在一定环境下,使用固定的套路去解决问题。 - 作用:提高软件系统可维护性以及代码的可复用性。
- 原则的目的:高内聚低耦合
- 高内聚:一个类只做一件事
- 低耦合:类和类之间的关系越弱越好。
- 这样在后期代码某一部分出错时,只需要修改对应部分,而不需要修改大量和这类关系密切的其他类。减少工作量和出错的概率。
- 类的单一原则:类的职责单一,只对外提供一种功能
- 类的开闭原则:类的改动是通过增加代码实现的而不是通过修改代码实现的。
- 单例模式:分为懒汉式单例模式和饿汉式单例模式
懒汉式单例模式:static 声明的变量在整个程序退出时释放,所谓的单例就是整个类只有一个全局对象,该对象使用static声明,变为类成员,并且构造函数被私有化,不能被外界随随便便的实例化,这个类成员在外部被赋予一个特殊值,才能声明这个唯一的对象。
这里在类直接调用类属性(等于特殊值才可以,比如nullptr)instance时,才可以初始化,并且使用public的getInstance函数自动接收这个初始化的属性值,然后在这个函数中唯一的创建这个类的唯一对象。也就是唯一接口供外部使用
优点是第一次调用的时候才初始化,避免内存浪费。缺点是必须加锁才能保证单例
#include <iostream>
using namespace std;
//懒汉式单例模式
class SingletonLazy {
private:
static SingletonLazy* instance;
// 构造函数私有化, 不让外界利用new创建实例
SingletonLazy() {
cout << "懒汉式单例模式\n";
}
public:
static SingletonLazy* getInstance() {
//第一次引用时才被实例化,只有在外部被使用类名进行调用时才初始化我们的唯一对象,没有外部调用那么就不被初始化来占用内存。
if (instance == nullptr) {
instance = new SingletonLazy;
}
return instance;
}
};
SingletonLazy* SingletonLazy::instance = nullptr;
//饿汉式单例模式
class SingletonHungry {
private:
static SingletonHungry* instance2;
SingletonHungry() {
cout << "饿汉式单例模式\n";
}
public:
static SingletonHungry* getInstance() {
return instance2;
}
};
//private下的static变量虽然类外无法通过类直接访问,但是可以类外进行初始化
//加载时实例化,这里是类外对类内私有唯一对象 instance2进行初始化,其他在类外单独定义的对象不能被初始化,因为无法使用new SingletonHungry语句,也就是调用私有的构造函数。调用不了而对于类内唯一静态对象类内声明类外初始化符合原则,虽然类外初始化,但是使用范围还是类内,所以可以调用该类的私有构造函数对其进行初始化。
//不管后面是否调用函数,我们唯一的对象都被初始化了。
SingletonHungry* SingletonHungry::instance2 = new SingletonHungry;
int main() {
//外部可以直接通过类方法getInstance直接调用获得该唯一的对象
cout << SingletonHungry::getInstance << endl;
cout << "action: \n";
system("pause");
return 0;
}
- 饿汉式单例模式:
缺点:不管用不用,都会初始化,造成内存资源浪费
优点:不需要加锁,执行效率高,线程安全的 - 策略模式:
策略模式:定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换,具体实现与客户端完全分离,客户端只需要操作一个类就可以实现不同功能
优点:1、减少了算法与使用算法之间的耦合度。 2、测试方便,每个算法都有自己的类,只要测试自己接口就行了,不影响其他算法
每一个策略都是一个算法
#include <iostream>
#include <string>
using namespace std;
//策略抽象类,定义所有支持的算法的公共接口
class CashSuper {
public:
virtual double acceptCash(double money) {
return money;
}
};
//具体策略类
class NormalFee :CashSuper {
public:
double acceptCash(double money) {
return money;
}
};
class DiscountFee :CashSuper {
public:
float discountNum;
public:
DiscountFee(float discountNum) {
this->discountNum = discountNum;
cout << endl;
}
double acceptCash(double money) {
return money * this->discountNum;
}
};
class ReturnFee :CashSuper {
public:
int fill;
int send;
public:
ReturnFee(int fill, int send) :fill(fill), send(send) {}
double acceptCash(double money) {
if (money > this->fill) {
return money - send;
}
return money;
}
};
//用一个具体策略来配置维护一个对策略对象的引用
CashContext 为具体算法和客户端之间的桥梁
//客户端可以根据不同的需求通过CashContext获得不同的结果
class CashContext {
private:
CashSuper* cs = nullptr;
public:
CashContext(int type) {
switch (type) {
case 0:
cs = (CashSuper*) new NormalFee;
break;
case 1:
cs = (CashSuper*)new DiscountFee(0.8);
break;
case 2:
cs = (CashSuper*) new DiscountFee(0.7);
break;
case 3:
cs = (CashSuper*) new DiscountFee(0.5);
break;
case 4:
cs = (CashSuper*) new ReturnFee(300, 100);
break;
}
}
//根据不同策略对象来实现不同结果
double getResult(double money) {
return cs->acceptCash(money);
}
};
int main()
{
//实例化打八折类
CashContext cc(1);
//获取打折后金额
double res = cc.getResult(100);
cout << res << endl;
return 0;
}
总结,如果将满减和打8折以及原价放一起(同一个类),假如打折或者原价代码出错,也会导致满减代码无法运行,也就无法实现满减功能,所以降低各个小功能之间的耦合度势在必行。,各个算法单独封装成一个个类,就是一个个不同的策略。
具体C++设计模式参考教程:https://blog.csdn.net/qq_46423987/article/details/126702565