一、单例模式
1.饿汉模式
2.懒汉模式
二、工厂模式
三、建造者模式
四、代理模式
设计模式是前辈们对代码开发的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
设计模式的六大原则:
1.单一职责原则
类的职责应该单一,一个方法只做一件事。职责划分清晰,每次改动到最小单位的方法或者类
使用建议:两个完全不一样的功能不应该放在同一个类中,一个类应该是一组相关性很高的函数,数据的封装
用例:网络聊天:通信类,聊天类
2.开闭原则
对扩展开发,对修改封闭
使用建议:对软件实体改动,最好使用扩展而非修改的方式
用例:超市卖货:商品价格 不是修改原来的商品价格,而是新增促销的价格
3.里氏替换原则
不要破坏继承体系
父类可以出现的地方,子类就可以出现,而且替换为子类也不会产生错误或者异常
在继承时,务必完全重写父类的方法,尤其是父类的protected方法,子类尽量不要暴露自己的public方法供外界调用
使用建议:子类完全实现父类的方法,子类可以有自己的个性,覆盖或者实现父类的方法时,输入参数可以被放大,输出可以缩小
用例:跑步运动员类-会跑步 子类长跑运动员:会跑步且擅长长跑,子类短跑运动员:会跑步且擅长短跑
4.依赖倒置原则
面向接口编程
高层次模块不应该依赖低层次模块,两者都应该依赖其抽象,不可分割的原子逻辑就是低层模式,原子逻辑组装成的就是高层模块
模块直接按依赖通过抽象(接口)发生,具体类之间不直接依赖
使用建议:每个类都尽量有抽象类,任何类都不应该从具体类派生。尽量不要重写基类的方法,结合里氏替换原则使用
用例:奔驰类司机--只能开奔驰 司机类--给什么车就开什么车 开车的人:司机 依赖抽象
5.迪米特法则 "最少知道法则"
降低耦合
尽量减少对象间的交互,从而减小类之间的耦合。一个对象应该其他对象有最少的了解,对类的低耦合提出明确的交流
用力:老师让班长点名 老师给班长一个名单,班长完成点名勾选,返回结果,而不是班长点名,老师勾选
6.接口隔离原则
客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口
使用建议:接口设计尽量精简单一,不要对外暴露没有实际意义的接口
用例:修改密码,就提供单一的最小修改密码接口,不应该提供用户信息接口,更不要暴露数据库
一个类只能创建一个对象,即单例模式,该设计模式中可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
那我们需要保证:
1)该类不能被拷贝构造,不能赋值。
2)构造函数私有
单例模式有两种实现方式:饿汉模式和懒汉模式
a.直接定义静态对象
b.静态指针+类外初始化时new
程序启动时候就会创建一个唯一的实例对象。因为单例对象已经确定,所以比较适用于多线程环境中,多线程获取单例对象不需要加锁,可以有效避免资源竞争,提高性能。缺点就是如果单例对象构造特别耗时或者耗费资源(加载插件,加载网络资源等)比较占用内存
template
class singleTon
{
private:
singleTon()
{
}
~singleTon()
{
}
public:
singleTon(const singleTon&) = delete;
singleTon& operator=(const singleTon&) = delete;
static T& getInstance()
{
return _eton;
}
private:
static singleTon _eton;
};
singleTon singleTon::_eton;
第一次要使用的时候创建实例对象。
a.静态指针+用到的时候初始化
b.局部静态变量
template
class singleTon{
private:
singleTon(){}
~singleTon(){}
public:
singleTon(const singleTon&) = delete;
singleTon& operator=(const singleTon&) = delete;
static T& getInstance()
{
static singleTon _eton;
return _eton;
}
};
工厂模式是一种创建型设计模式,在工厂模式中,创建对象时候不会对上层暴露创建逻辑,而是通过一个共同结构指向新创建的对象,以此实现创建-使用的分离
1.简单工厂模式
简单工厂模式实现由一个工厂对象通过类型决定创建出来指定产品类的实例。假设有个工厂可以生产水果,客户需要产品的时候明确告知工厂生产哪类水果,工厂需要接收用户提供的类别信息,当新增产品的时候,工厂内部去添加新产品的生产方式。
这个模式的结构和管理对象的方式十分简单,但是它的可扩展性非常差,当我们需要新增产品的时候,就需要修改工厂类新增一个类型的产品创建逻辑,违背了开闭原则。
class Fruit
{
public:
Fruit(){}
virtual void show() = 0;
};
class Apple :public Fruit
{
public:
Apple(){}
virtual void show()
{
cout<<"apple method..."< create(const std::string &name)
{
if(name =="Apple")
return std::make_shared();
else if(name =="banana")
return std::make_shared();
}
return std::shared_ptr();
}
};
int main()
{
std::shared_ptr fruit = FruitFactory::create("Apple");
fruit->show();
return 0;
}
2.工厂方法模式
在简单工厂模式下新增多个工厂,多个产品,每个产品对于一个工厂。假设有a,b两种产品,则开两个工厂,工厂a负责生产产品a,工厂b生产产品b,用户只知道产品的工厂名,而不知道具体的产品信息,工厂不需要再接收客户的产品类别,而只负责生产产品。
工厂方法模式每次增加一个产品时,都需要增加一个具体产品类和工厂类,这会使得系统中类的个数成倍增加,在一定程度上增加了系统的耦合度。
class Fruit
{
public:
Fruit(){}
virtual void show() = 0;
};
class Apple :public Fruit
{
public:
Apple(){}
virtual void show()
{
cout<<"apple method..."< create()
{
return std::make_shared();
}
};
class BananaFactory:public FruitFactory
{
public:
virtual std::shared_ptr create()
{
return std::make_shared();
}
};
int main()
{
shared_ptr Factory());
fruit = Factory->create();
fruit->show()
return 0;
}
3.抽象工厂模式
工厂方法模式引入工厂等级结构,解决了简单工厂模式中工厂类职责太多的问题,但是由于工厂方法模式每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,会增加系统的开销。此时可以将一些相关的产品组成一个产品族(位于不同产品等级结构中功能相关联的产品组成的家族),由同一个工厂来生产,这就是抽象工厂模式的基本思想。
抽象工厂模式适用于生产多个工厂系列产品衍生的设计模式,增加新的产品等级结构复杂,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,违背了“开闭原则”。
//围绕一个超级工厂创建其他工厂,每个生产的工厂按照工厂模式提供对象。
//思想:将工厂抽象成两层, 抽象工厂 & 具体工厂子类,在子类中生产不同的子产品
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 getFruit(const std::string &name) = 0;
virtual std::shared_ptr getAnimal(const std::string &name) = 0;
};
class FruitFactory : public Factory {
public:
virtual std::shared_ptr getAnimal(const std::string &name) {
return std::shared_ptr();
}
virtual std::shared_ptr getFruit(const std::string &name) {
if (name == "苹果")
{
return std::make_shared();
}
else if(name == "⾹蕉")
{
return std::make_shared();
}
return std::shared_ptr();
}
};
class AnimalFactory : public Factory {
public:
virtual std::shared_ptr getFruit(const std::string &name) {
return std::shared_ptr();
}
virtual std::shared_ptr getAnimal(const std::string &name) {
if (name == "⼩⽺") {
return std::make_shared();
}else if(name == "⼩狗") {
return std::make_shared();
}
return std::shared_ptr();
}
};
class FactoryProducer {
public:
static std::shared_ptr getFactory(const std::string &name) {
if (name == "动物") {
return std::make_shared();
}else {
return std::make_shared();
}
}
};
int main()
{
std::shared_ptr fruit_factory = FactoryProducer::getFactory("⽔果");
std::shared_ptr fruit = fruit_factory->getFruit("苹果");
fruit->show();
fruit = fruit_factory->getFruit("⾹蕉");
fruit->show();
std::shared_ptr animal_factory = FactoryProducer::getFactory("动物");
std::shared_ptr animal = animal_factory->getAnimal("⼩⽺");
animal->voice();
animal = animal_factory->getAnimal("⼩狗");
animal->voice();
return 0;
}
建造者模式是一种创建型设计模式,使用多个简单的对象一步一步构建成一个复杂的对象,能够将一个复杂的对象的构建与它的表示分离,提供一种创建对象的最佳方式。主要用于解决对象的构建过于复杂的问题。
建造者模式主要基于四个核心类实现:
抽象产品类;
具体产品类;
抽象builder类:创建一个产品对象所需的各个部件的抽象接口
具体产品的builder类:实现抽象接口,构建各个部件
指挥者director类:统一组件过程,提供给调用者使用,通过指挥者来构造产品
//抽象电脑类
class Computer
{
public:
using ptr = std::shared_ptr;
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:
using ptr = std::shared_ptr;
MacBook() {}
virtual void setOs() {_os = "Max Os X12";}
};
//抽象建造者类 包含创建一个产品对象各个部件的抽象接口
class Builder
{
public:
using ptr = std::shared_ptr;
virtual void buildBorad(const std::string &board) = 0;
virtual void buildDisplay(const std::string &display)=0;
virtual void buildOs()=0;
virtual Computer::ptr build() = 0;
};
//具体产品的具体建造者类,实现抽象接口,构建和组装各个部件
class MacBookBuilder:pubilc Builder
{
public:
using ptr = std::shared_ptr;
MacBookBuilder()
:_computer(new MackBook()){}
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();
}
private:
Computer:: ptr _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:
Builder::ptr _builder;
};
int main()
{
Builder * builder = new MacBookBuilder();
std:: unique_ptr pd(new Director(builder));
pd->construct("Inter","aoc");
Computer:: ptr computer = builder->build();
return 0;
}
代理模式指的是代理控制对其他对象的访问,也就是代理对象控制原对象的引用。在某些情况下,一个对象不适合或者不能直接引用访问,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式结构包括:一个真正要访问的对象(目标类),一个是代理对象。
目标类和代理对象实现一个接口,先访问代理对象再通过代理对象访问目标对象。
代理模式分为:静态代理和动态代理
- 静态代理指的是,在编译时就已经确定好了代理类和被代理类的关系。也就是说,在编译时就已经 确定了代理类要代理的是哪个被代理类。
- 动态代理指的是,在运⾏时才动态⽣成代理类,并将其与被代理类绑定。这意味着,在运⾏时才能 确定代理类要代理的是哪个被代理类
以租房为例,房东将房⼦租出去,但是要租房⼦出去,需要发布招租启⽰, 带⼈看房,负责维修,这 些⼯作中有些操作并⾮房东能完成,因此房东为了图省事,将房⼦委托给中介进⾏租赁
class RentHouse
{
public:
virtual void rentHouse() = 0;
};
//房东类
class LandLord: public RentHouse
{
public:
void rentHouse()
{
cout<<"rent.."<