C++设计模式


模式设计的六大原则

六大设计原则超详细介绍(再不理解你打我)

单一职责原则

⼀个类应该仅有⼀个引起它变化的原因。

解释: 一个类或函数只承担一个职责。
比如一个用户类有一个修改账号和密码的成员函数,那这个成员函数就承担了两个职责:修改账号和修改密码,它们之间相互耦合。用户如果只想修改密码或者只想修改账号就得调用同一个函数,给调用增加了麻烦。如果后续增加修改邮箱的功能,是不是还得给这个函数增加修改邮箱的功能?

class User1 {
public:
	//修改账号和密码
	bool ModifyUserInformation(string information, int op){
		//如果op为1,则修改账号
		if (op == 1){

		}
		//op为2,修改密码
		else if (op == 2){

		}
		//如果后续还要增加修改邮箱的功能,还需要传入op==3,这不仅不好维护
		//而且也不方便程序员调用这个函数,因为并不知道op填多少
	}
private:
	//用户的账号
	string _user_name;
	//用户的密码
	string _user_password;
	//用户的邮箱
	string _user_email;
};
class User2 {
public:
	//修改账号
	bool ModifyUserName(string new_name){
		
	}
	//修改账号
	bool ModifyUserPassword(string new_password) {

	}
	//如果后续增加修改邮箱的功能,只需要再加一个成员函数即可
private:
	//用户的账号
	string _user_name;
	//用户的密码
	string _user_password;
	//用户的邮箱
	string _user_email;
};

再举一个例子,比如一个抽象类“家务”有两个函数“洗碗”和“拖地”,另外两个用户类,一个类只负责“洗碗”,一个类只负责“拖地”。

class HouseWork {
public:
	virtual void WashDishes() = 0;
	virtual void Mopping() = 0;
};
class User1 : public HouseWork {
public:
	void WashDishes(){
		cout << "用户1负责洗碗" << endl;
	}
	//因为父类是抽象类,所以User1必须要实现这个拖地的接口,即使它不负责拖地
	void Mopping() {};
};
class User2 : public HouseWork {
public:
	void WashDishes() {};
	void Mopping() {
		cout << "用户2负责拖地" << endl;
	}
};

可以看到上面抽象类HouseWork有两个功能,User1和User2只需要其中一个功能时,还必须要实现另一个功能。并且如果HouseWork增加一个函数,比如做饭。那User1和User2就必须要再实现做饭这个函数,这是非常麻烦的。

因此,我们可以把这些功能分离出来单独实现成一个类:

class HouseWork {
};
//洗碗和拖地分离
class Wash:public HouseWork {
public:
	virtual void WashDishes() = 0;
};
class Mop :public HouseWork{
public:
	virtual void Mopping() = 0;
};
//如果想增加做饭的接口
class Cook :public HouseWork {
public:
	virtual void Cooking() = 0;
};
class User1 : public Wash {
public:
	void WashDishes() {
		cout << "用户1负责洗碗" << endl;
	}
};
class User2 : public Mop {
public:
	void Mopping() {
		cout << "用户2负责拖地" << endl;
	}
};
//User3负责拖地和做饭
class User3 : public Mop,Cook {
public:
	void Mopping() {
		cout << "用户3负责拖地" << endl;
	}
	void Cooking() {
		cout << "用户3负责做饭" << endl;
	}
};

里氏替换原则

子类在继承类时,必须重写父类中所有的抽象函数。子类可以实现自己的函数,但不能覆盖掉父类的非抽象函数。

子类的对象能够替换其基类的对象被使用。

解释: 前面很好理解,在继承时经常用:

#include <iostream>
//鸟
class Bird {
public:
    Bird() {}
    virtual ~Bird() {}
    virtual void Fly() {
        std::cout << "I am  a bird and I am flying" << std::endl;
    }
};
//燕子
class Swallow : public Bird {
public:
    Swallow() {}
    ~Swallow() {}
    void Fly() override {
        std::cout << "I am  a Swallow and I am flying" << std::endl;
    }
};
//大雁
class WildGoose : public Bird {
public:
    WildGoose() {}
    ~WildGoose() {}
    void Fly() override {
        std::cout << "I am  a Wild Goose and I am flying" << std::endl;
    }
};
//模拟鸟的飞行
void Fly(Bird& b) {
    b.Fly();
}

int main() {
    WildGoose goose;
    Swallow s;
    Fly(s);
    Fly(goose);
}

子类的对象能够替换其基类的对象被使用。比如:任何使用Animal抽象类的地方,我们都可以用其子类如Cat类替代,因为Cat类重写了Animal的各种抽象函数。

依赖倒置原则

模块间的依赖通过抽象发生,实现类之间不直接发生依赖关系,其依赖关系是通过接口或抽象类产生的;抽象不应该依赖具体实现,具体实现应该依赖于抽象类。

解释: 直接通过例子来说明,现在有两个类,披萨类和用户类,用户可以执行吃披萨的动作:

class Pizza {
public:
	void eated() {
		cout << "披萨正在被吃" << endl;
	}
};
class User {
public:
	void eat(Pizza food) {
		cout << "用户正在吃饭" << endl;
		food.eated();
	}
	//这样实现eat有很大的问题,比如后续如果增加吃汉堡的功能
	//那还需要再实现一个eat函数
};

可以发现如果后续用户想要增加吃汉堡的功能,就得再写一个eat函数。为了解决这个问题,我们可以将它们之间的依赖关系抽象出来:

//使用抽象类解决了Food和User的依赖关系
class Food
{
public:
    virtual void eated() = 0;
};
class IUser
{
public:
    virtual void eat(Food *) = 0;
};

class Pizza : public Food
{
public:
    void eated()
    {
        cout << "披萨正在被吃" << endl;
    }
};
class Hamburger : public Food
{
public:
    void eated()
    {
        cout << "汉堡正在被吃" << endl;
    }
};
class User1 : public IUser
{
public:
    void eat(Food *food)
    {
        cout << "用户正在吃饭" << endl;
        food->eated();
        //后续如果想增加吃其他食物的功能,比如吃饺子
        //直接实现一个饺子类即可,不需要再写一个eat函数
    }
};
int main()
{
    User1 u1;
    u1.eat(new Pizza);
    u1.eat(new Hamburger);
}

在这里插入图片描述

接口隔离原则

建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

这和“单一职责原则”类似,但它们还有一些不同:

  • 单一职责原则:一个类或函数只承担一个职责,所以同一个功能的所有实现函数可能会放到同一个类中。

  • 接口隔离原则:减少接口的粒度,每个类只需要实现自己需要的接口即可。

所以单一职责原则和接口隔离原则可能会无法同时保证。

迪米特法则

尽量减少对象之间的交互,从而减小类之间的耦合。

开闭原则

当增加新功能,不应该通过修改已经存在的代码来进行,而是应该通过扩展代码,比如增加新类、增加新的成员函数 来实现。


C++各种设计模式

正在完善,后面再写。。。。

模板方法模式

C++设计模式—模板方法模式

工厂模式

C++设计模式----工厂模式
C++设计模式—原型模式
C++设计模式—建造者/构建器/构建者/生成器模式

策略模式

C++设计模式—策略模式

观察者模式

C++设计模式—观察者模式

装饰器模式

C++设计模式----装饰器模式

单例模式

C++ 特殊类的设计
C++设计模式—单例模式

外观模式

C++设计模式—外观模式

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天也要写bug、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值