学习软件设计模式有利于对面向对象的加深理解,设计模式是由GOF提出来的,主要用于一套解决问题的固定模式。

设计模式有23种,分为3类(简单了解):1、创建型模式:针对如何创建对象的模式。 2、结构型模式:如何实现类或对象 3、行为型模式:类或对象怎么样进行交互和职责分配。 除此之外,还有一种“简单工厂模式”,但是不属于23种之一。

设计模式最核心的思想是“多态”,如果不熟悉先复习一下; 在介绍23种设计模式之前,先简单介绍6种面向对象的设计原则。其实就是“高内聚、低耦合”。什么是高内聚? 比如说我和你有两张银行卡,我们都能实现存钱取钱的功能,但是我存取和取钱是不会对你造成影响的。简而言之,我的类中的内容对你是不可见的,这就是内聚。至于有多高呢~  可能需要我们的代码是可扩展,可复用,可维护的等等。什么是低耦合呢?  耦合就是关联的意思,低耦合就是关联性很低。举个例子,可能很多人不知道为什么我们接入一个设备需要装“驱动”,比如显卡驱动,鼠标键盘驱动等。 不管你用的是雷蛇的鼠标,还是双飞燕的鼠标,插入电脑都可以使用啊。这两种鼠标本来就没有关系,它们是"低耦合"的,但是他们各自的厂商给他们提供了“驱动”(具体实现),使得它们能实现各自功能。所以即使他们一点关系都没有,还是能在一台电脑上使用,这就是“解耦合”。这种设计理念很重要, 下面介绍由“高内聚,低耦合”演变来的6大原则。

1、单一职责原则(SRP):我们希望每个类的功能都是单一的,对外只提供一个功能,就像对待爱情一样要一心一意。

2、开闭原则(OCP):有个成语叫“牵一发而动全身”,如果我们改变了某段代码,可能会导致整个程序都出错。那么最好的办法是只增加代码不修改代码。下面看个例子:假如我们要描述各行各业的人。

class Person {//....public:void Banker() {cout << "有钱" << endl; }void Doctor() {cout << "救死扶伤" << endl;}void Teacher() {cout << "辛勤园丁"}....
};

但是各行各业的人太多了,如果我们不断添加。那就是三百六十行,行行累死人了!

此时我们可以采取继承/组合的方法:

class Person
{//纯虚函数用于描述不同的人特点virtual void trait() = 0;
};class Banker:public Person
{virtual void trait(){cout << "有钱" << endl;}
};class Teacher :public Person
{virtual void trait(){cout << "辛勤园丁" << endl;}
};class Doctor :public Person
{virtual void trait(){cout << "救死扶伤" << endl;}
};

乍一看多了很多代码,那岂不是变得更复杂了? 虽然代码变多了,但是我们可以为所欲为不断添加,不怕在一个类中出错崩掉了。这样就可以让小伙伴每人负责写一个类,而不用一起堆在一起写一个类,这样你修改一下我修改一下就乱了套。

3、迪米特原则(Lod):又叫最少知识原则。一个对象应当对其他对象知道的越少越好。这样是为了降低他们之间的耦合性。

在一个程序里,如果不同的模块要相互调用,我们一般抽象出一个基类(接口)来实现。这样一个模块就不用了解另一个模块里面的细节,举个例子:比如说炒股,稳健的我们一般不会直接买股票,而是去买投资基金,委托金融机构去替我们买股票。那么金融机构就会帮我们去买A股、B股... 事实上我们不需要知道他们买的是什么股票,我们只需要知道我们赚钱没有。因此我们可以将这个过程抽象成这样:

class stock
{
public:virtual string getType() = 0;  //记录股票类型virtual void getProfit() = 0; //看看赚没赚钱
};
//为了方便,我们假设A股赚钱,B股亏钱吧
class AStock :public stock {
public:AStock(){profit = "赚钱啦!";stype = "A股";}virtual void getProfit(){cout << stype << profit << endl;}virtual string getType(){return stype;  //让中介看看赚没赚钱}
private:string profit;string stype;
};class BStock : public stock {
public:BStock(){profit = "亏钱啦!";stype = "B股";}virtual void getProfit(){cout << stype << profit << endl;}virtual string getType(){return stype;  //让中介看看赚没赚钱}
private:string profit;string stype;
};
//中介类:
class Agent {
public:Agent(){stock * st = new AStock;  //多态,父类指针指向子类。 买了A股vStock.push_back(st);  //装兜里st = new BStock; //买B股vStock.push_back(st); //装兜里//....  可以继续买}~Agent(){//析构上面两个指针for (vector<stock *>::iterator it = vStock.begin(); it != vStock.end(); it++){if (*it != NULL)delete *it;}}//提供购买基金的方法stock * buyFund(string  type){for (vector<stock *>::iterator it = vStock.begin(); it != vStock.end(); it++){if ((*it)->getProfit == type)  //看下买的是哪只股票return *it;}return NULL;}
private:vector<stock *> vStock;  //存放中介买的股票
};int main()
{Agent *ag = new Agent;stock *st = ag->buyFund("A股"); //假设中介去买了A股st->getProfit();  //输出"赚钱啦!"
}

注意:倒数第二句,我们并不知道中介买的是什么股票。 我们得到的是只是中介买完股票返回的一个stock类型的指针st,通过这个指针调用getProfit方法我们的就知道赚钱了(具体看多态原理)。这样通过开闭原则实际上我们就是利用一个中间层来帮我们管理。

4、合成复用原则(CRP):上面的例子我们使用了继承,但是继承存在缺陷:如果父类改动了,那么对应子类也就改动了。而且复用性也很差,所以建议使用组合而不是继承!比如:

class grandfather {
protected://money;
};class father :public grandfather{
protected://money;
};class mother {
protected://money
};class son : public father ,public mother{ //如果还想继承,就要继续写下去,越写越长...
protected://money;
};class grandson :public son {
protected://money;
};

正所谓富不过三代,但是穷却可以一直继承下去。就如上面的例子,如果父类一"穷",那么所有子类就可能跟着“穷”了。

因此我们最好改成这样:

class father {
protected://money;
};class mother {
protected://money
};class son {//ft.money;son(mother &mt){}
private:father ft;
};

改成上面这样就清爽很多了,注意上面展现两种组合方式。这样son类就不用受father类和mother的约束了,可以需要的时候再调用它们的money!继承和组合我们首先选择组合方式!

5、里氏代换原则(LSP):实际上就是“多态”,完成虚拟机制。任何的抽象类都可以使用它的实现类进行替换。上面的几个实现代码都有使用过。

6、依赖倒转原则(DIP):就是对接口编程,而不要依赖具体的实现类。实际上就是依赖“多态”。

在传统开发中,我们很容易写出依赖性很强的代码。比如:

这样就会层层依赖,导致“牵一发而动全身”。看一个例子,假如我们要开发一个对战游戏

//顶层业务
class skill
{
public:void duixian() {/*描述*/}; //对线void daye() {/*描述*/ };    //打野void chayan() {/*描述*/ };  //插眼void kangta() {/*描述*/ };  //抗塔//...
};
//中间层
void doDuixian(skill *sk){sk->duixian();
}
void doDaye(skill *sk){sk->daye();
}
void doChayan(skill *sk){sk->chayan();
}
void doKangta(skill *sk){sk->kangta();
}
//测试
void test()
{skill * mangseng = new skill;doDaye(mangseng); //让盲僧去打野
}

这样写是有弊端的,形成了层层依赖的关系。 mangseng对象是依赖于中间层的doDaye的方法的,而doDaye是依赖于daye方法的。假设daye方法规定mangseng不能打野了,那我们再在doDaye中写“红开”,“蓝开”是没有意义的。另一方面,skill类实现的功能太多了,违背了我们第一条单一职责原则。实际上,这些操作都是人的操作,我们可以搞一个“人”的抽象层:

//抽象层
class Person {
public:virtual void doSkill() = 0;
};//中间层
class daye :public Person {
public:virtual void doSkill() {cout << "打野" << endl;}
};
class duixian :public Person {
public:virtual void doSkill() {cout << "对线" << endl;}
};
class chayan :public Person {
public:virtual void doSkill() {cout << "插眼" << endl;}
};
class kangta :public Person {
public:virtual void doSkill() {cout << "抗塔" << endl;}
};
void DifferentSkill(Person *person) { person->doSkill();
}
//测试
void test() {Person *mangseng = new daye;DifferentSkill(mangseng); //这里并不依赖中间层,而是传入Person,运行时会动态绑定//打印:“打野”
}

设计模式(一) 六大原则相关推荐

  1. 【设计模式 00】设计模式的六大原则

    设计模式的六大原则 参考: 设计模式六大原则 1. 单一职责原则 一个类只负责一个明确的功能 优点: 降低类的复杂度,提高代码可读性和可维护性 降低变更时对其他功能的影响 2. 里氏替换原则 **原则 ...

  2. 神了!有人用一个项目把23种设计模式与六大原则融会贯通了

    前言 设计模式分为三类,创建型,结构型和行为型.创建型比较好理解,它抽象了实例化过程,将系统与实例的创建解耦.实例由专门的工厂来创建,从而使系统针对实例的抽象接口编程,不依赖任何具体的实现.结构型和行 ...

  3. 如何理解设计模式的六大原则?

    我们知道,java中有类,父类,抽象类,接口这些概念,而设计模式的六大原则就解释了它们及其它们之间的关系是怎样的,接下来我们将由简到难一一剖析. 开闭原则:是总纲,他告诉我们要对扩展开放,对修改关闭. ...

  4. 设计模式的六大原则(SOLID)

    设计模式的六大原则有: Single Responsibility Principle:单一职责原则 Open Closed Principle:开闭原则 Liskov Substitution Pr ...

  5. unity 项目开发——浅谈设计模式的六大原则(一)

    目录 前言 首先,六大原则是谁? 其次,为什么需要学习这六大原则? 正文 一.单一职责原则 示例: 因此我们需要进行拆分,根据具体的职能可将其具体拆分如下: Unity 单一职责原则 二.开闭原则 U ...

  6. 设计模式的六大原则。简称:SOLID

    设计模式的六大原则.简称:SOLID 迪米特法则(Law of Demeter):如果两个类之间并不需要直接通信,那么就不应该让这两个类相互作用.又叫作最少知识原则 迪米特法则的定义是:只与你的直接朋 ...

  7. 「设计模式」六大原则之三:里氏替换原则小结

    文章目录 1.里式替换原则定义 2. 举例说明 示例1: 示例2: 3. 哪些代码明显违背了 LSP? 子类违背父类声明要实现的功能 子类违背父类对输入.输出.异常的约定 子类违背父类注释中所罗列的任 ...

  8. (转)设计模式之六大原则

    源地址:http://blog.csdn.net/scboyhj__/article/details/47844639 1. 单一职责原则 -Single Responsibility Princip ...

  9. 【设计模式】——六大原则

    ◎原则之间的关系◎ 开闭原则是目标,里氏转换原则是基础,依赖倒转原则是手段.六大原则追求的目标都是,可扩展,复用性强,灵活性高,容易维护,耦合度低. ★★单一职责原则★♬★ 定义:就一个类而言,应该仅 ...

  10. 何红辉设计模式之六大原则

    这篇文章总结的很到位: https://www.jianshu.com/p/807bc228dbc2 欢迎去阅读 设计模式六大原则 ,简称:solid 1.Single Responsibility ...

最新文章

  1. 一道微软面试题的运算过程解析
  2. 使用Def文件导出dll
  3. 深度学习助力异常胸部 X 光片检测
  4. UIImage 图片处理:截图,缩放,设定大小,存储
  5. 用canvas给自己的博客园加背景(二)
  6. vector迭代器的使用
  7. 【故障诊断分析】基于matlab概率神经网络柴油机故障诊断【含Matlab源码 1754期】
  8. RocketMQ(一)RocketMQ介绍及核心概念
  9. 屏蔽CDSN烦人的广告
  10. android 开机动画,修改安卓开机动画(除了部分系统 如MIUI等)
  11. PPT的配色方法(师从于珞珈老师)
  12. 电子管功放制作指南_电子管功率放大器的简易设计
  13. wordpress建站我们如何选择虚拟主机和VPS服务器呢?
  14. 数分笔记整理22 - 数据处理项目 - 中国姓氏排行研究 房价影响因素挖掘
  15. 云中漫步-我这一辈子
  16. linux下postgresql创表添加数据
  17. 上个厕所的功夫弄清楚了ES搜索服务器
  18. 最小生成树 | Prim算法 Kruskal算法 |C语言
  19. 工作流引擎WorkFlow开源项目
  20. 用多媒体计算机画图教学设计,Windows98中画图程序的使用教学设计.doc

热门文章

  1. RX 470 480 570 580 590 5700 6600 5600 6900 6800在WIN10上玩GTA5 闪退,无法运行,打不开,解决方案
  2. u盘linux运行速度慢,linux准确测量U盘读写速度
  3. 周遭心理学的应用-什么是心理学?
  4. Git和SVN的区别(以后别再问我了)
  5. IntelliJ IDEA 破解
  6. 区块链性能测试工具使用教程
  7. 靠谱助手微信版 v1.0 pc版
  8. 计算机网络原理-韩立刚-第四章 网络层
  9. 网易面试软件测试面试题
  10. QtDesigner配置