一:设计模式六大原则

1. 单一职责原则(single Responsibility Principle)

Single-Responsibilitiy Principle(SRP):对一个类而言,应该仅有一个引起它变化的原因。如果存在多于一个动机去改变一个类,那么这个类就具有多于一个的职责,就应该把多余的职责分离出去,再去创建一些类来完成每一个职责。

举个例子:一个人身兼数职,而这些事情相关性不大,甚至有冲突,那他就无法很好的解决这些问题职责,应该分到不同的人身上去做。

<?php
class Animal
{public function breathe($animal){echo $animal . "在空气中呼吸<br>";}
}class Program
{public function main(){$animal = new Animal();$animal->breathe("牛");$animal->breathe("羊");// 鱼是在水中呼吸,因此这样不妥$animal->breathe("鱼");}
}#------------------- 修正 ---------------------#
class Aquatic
{public function breathe($animal){echo $animal . "在水中呼吸<br>";}
}class Program2
{public function main(){$animal = new Animal();$animal->breathe("牛");$animal->breathe("羊");// 鱼是在水中呼吸$aquatic = new Aquatic();$aquatic->breathe("鱼");}
}

单一职责原则是实现高内聚低耦合的最好方法,没有之一。

2. 里氏代换原则(Liskov Substitution Principle)

Liskov Substitution Principle:子类可以扩展父类的功能,但是不能改变父类原有的功能。

在第一条原则开放封闭原则中,主张“抽象”和“多态”。维持设计的封装性“抽象”是语言提供的功能,“多态”由继承语意实现。因此如何去度量继承关系中的质量?

答案是:继承必须明确确保超类(父类)所拥有的性质在子类中仍然成立。

在面向对象的思想中,一个对象就是一组状态和一系列行为的组合体。状态是对象的内在特性,行为是对象的外在特性。LSP表述的就是在同一继承体系中的队形应该具有共同的行为特征。

<?php
class A
{public function subtract($a, $b){return $a - $b;}public function quadrature($a, $b){return $this->subtract($a, $b) * 100;}
}// 这种是修改,而非拓展
class B extends A
{public function subtract($a, $b){return $a + $b;}public function quadrature($a, $b){return $this->subtract($a, $b) * 100;}
}#------------------拓展--------------------#
abstract class D
{public abstract function subtract($a, $b);public function quadrature($a, $b){return $this->subtract($a, $b) * 100;}
}
// 通过子类继承实现抽象方法达到拓展目的
class E extends D
{public function subtract($a, $b){return $a + $b;}
}class F extends D
{public function subtract($a, $b){return $a - $b;}
}

3. 依赖倒置原则(Dependence Inversion Principle)

Dependence Inversion Principle(DIP):是一个类与类之间的调用规则。这里的依赖就是代码中的耦合。高层模块不应该依赖底层模块,二者都应该依赖其抽象了;抽象不依赖细节;细节应该依赖抽象。接口编程。

主要思想就是:如果一个类中的一个成员或者参数成为一个具体的类型,那么这个类就依赖这个具体类型。如果在一个继承结构中,上层类中的一个成员或者参数为一个下层类型,那么就是这个继承结构高层依赖底层,就要尽量面向抽象或者接口编程。

举例:存在一个Driver类,成员为一个Car对象,还有一个driver()方法,Car对象中有两个方法start()与stop()。显然Driver依赖Car,也就是说Driver类调用了Car类中的方法。但是当增加Driver类对于Bus类的支持时(司机有需要开公交车),就必须更改Driver中的代码,就破坏了开放封闭原则。根本原因在于高层的的Driver类与底层的Car类仅仅的耦合在一起的。解决方法之一就是:对Car类和Bus类进行抽象,引入抽象类Automoble。而Car和Bus则是对Automobile的泛化。

经过这样的改造发现,原本的高层依赖底层,变成了高层与底层同时依赖抽象。这就是依赖倒转原则的本质。

优点:

  • 低层模块尽量都要有抽象类或接口,或者两者都有
  • 变量的声明类型尽量是抽象类或接口
  • 使用继承时遵循里氏替换原则
<?php
/** 依赖倒置原则*/
class Book
{public function getContent(){return "在很久很久以前";}
}
class Newspaper
{public function getContent(){return "php是最好的语言";}
}
class Mother
{public function narrate(Book $book){echo $book->getContent();}
}$m = new Mother();
$m->narrate(new Book());#----------------改正----------------#
interface IReader
{public function getContent();
}
class Bookl implements IReader
{public function getContent(){return "在很久很久以前";}
}class Newspaperl implements IReader
{public function getContent(){return "php是最好的语言";}
}class Motherl
{public function narrate(IReader $iRead){echo $iRead->getContent();}
}$ml = new Motherl();
$ml->narrate(new Bookl());
$ml->narrate(new Newspaperl());

4. 接口隔离原则(Interface Segregation Principle)

接口隔离原则(Interface Segregation Principle):用于恰当的划分角色和接口,具有两种含义:1、用户不应该依赖它不需要的借口;2、类间的依赖关系应该建立在最小的的接口上。

将这两个定义概括为一句话:建立单一接口,代替庞大臃肿的接口。通俗来说就是:接口尽量细化,同时保证接口中的方法尽量的少。一个接口中包含太多的行为时,会导致它们与客户端的不正常依赖关系,要做的就是分离接口,从而实现解耦。

回到上述的单一职责原则,要求行为分离接口接口细化,感觉有些相同。但实际上,单一职责原则要求类与接口的职责单一,注重的是职责,没有要求接口尽量的少。

在接口隔离原则中,要求尽量使用多个专门的接口。专门的接口也就是提供给多个模块的接口。提供给几个模块就应该有几个接口,而不是建立一个臃肿庞大的接口,所有的模块都可以访问。

但是接口的设计是有限度的。接口的设计粒度越小系统越灵活,这是事实,但是接口太多这也就使得结构复杂,维护难度大。因此实际中,怎样把握就靠开发的经验和常识了。

<?php
/** 接口隔离原则*/
interface I
{public function method1();public function method2();public function method3();public function method4();public function method5();
}class A
{public function depend1(I $i){$i->method1();}public function depend2(I $i){$i->method2();}public function depend3(I $i){$i->method3();}
}class B implements I{public function method1(){}public function method2(){}public function method3(){}public function method4(){}public function method5(){}
}class C
{public function depend1(I $i){$i->method1();}public function depend2(I $i){$i->method2();}public function depend3(I $i){$i->method3();}
}class D implements I{public function method1(){}public function method2(){}public function method3(){}public function method4(){}public function method5(){}
}$a = new A();
$a->depend1(new B());
$a->depend2(new B());
$a->depend3(new B());$c = new C();
$c->depend1(new D());
$c->depend2(new D());
$c->depend3(new D());#------------------修正-------------------#
interface I1
{public function method1();
}
interface I2
{public function method2();public function method3();
}
interface I3
{public function method4();public function method5();
}
class Al
{public function depend1(I1 $i){$i->method1();}public function depend2(I2 $i){$i->method2();}public function depend3(I2 $i){$i->method3();}
}
class Bl implements I1, I2{public function method1(){}public function method2(){}public function method3(){}
}
class Cl
{public function depend1(I1 $i){$i->method1();}public function depend2(I3 $i){$i->method4();}public function depend3(I3 $i){$i->method5();}
}
class Dl implements I1, I3{public function method1(){}public function method4(){}public function method5(){}
}
$a = new Al();
$a->depend1(new Bl());
$a->depend2(new Bl());
$a->depend3(new Bl());$c = new Cl();
$c->depend1(new Dl());
$c->depend4(new Dl());
$c->depend5(new Dl());

5. 迪米特原则(Law of Demeter)

Law of Demeter(最小知识原则):一个对象应该对其他对象有最少的了解。通俗来说就是,一个类对自己需要耦合或者调用的类知道的最少,你类内部怎么复杂,我不管,那是你的事,我只知道你有那么多公用的方法,我能调用。

迪米特原则不希望类与类之间建立直接的接触。如果真的需要有联系,那么就通过它们的友元类来传达。举例来说:你需要买房子了,现在存在三座合适的楼盘A,B,C,但是你不必直接去楼盘买楼,而是在售楼处去了解情况。这样就减少了你(购房者)与楼盘两个类之间耦合。

但是应用迪米特原则很可能会造成一个后果:系统会存在大量的中介类,这些类(如上面的售楼处类)之所以存在是为了传递类之间的相互调用关系,这就一定会程度上增加了系统的复杂度。

迪米特原则核心观念就是:类间解耦,弱耦合。

<?php
/** 迪米特原则(最少知道原则)*/
class SubCompanyManager
{public function getAllEmployee(){$arr = [];for($i = 0; $i < 40; $i++) {$arr[$i] = $i;}return $arr;}
}class CompanyManager
{public function getAllEmployee(SubCompanyManager $sub){for ($i = 0; $i < 30; $i++){echo "总公司" . $i . "<br>";}$arr = $sub->getAllEployee();foreach ($arr as $v) {echo "分公司" . $v . "<br>";}}
}$sub = new SubCompanyManager();
$class = new CompanyManager();
$class->getAllEmployee($sub);#-------------------改正----------------------#
class SubCompanyManagerl
{public function getAllEmployee(){for($i = 0; $i < 40; $i++) {echo "分公司" . $i . "<br>";}}
}class CompanyManagerl
{public function getAllEmployee(SubCompanyManagerl $sub){for ($i = 0; $i < 30; $i++){echo "总公司" . $i . "<br>";}$sub->getAllEployee();}
}$subl = new SubCompanyManagerl();
$classl = new CompanyManagerl();
$classl->getAllEmployee($subl);

6. 开闭原则(open close Principle)

Open-Close Principle(OCP):一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。目的就是保证程序的扩展性好,易于维护和升级。

开闭原则被称为面向对象设计的基石,实际上,其他原则都可以看作是实现开闭原则的工具和手段。意思就是:软件对扩展应该是开放的,对修改是封闭的,通俗来说就是,开发一个软件时,应该对其进行功能扩展,而在进行这些扩展时,不需要对原来的程序进行修改。

好处是:软件可用性非常灵活,扩展性强。需要新的功能时,可以增加新的模块来满足新需求。另外由于原来的模块没有修改,所以不用担心稳定性的问题。

如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:瞳孔的个人网站

设计模式六大原则详解相关推荐

  1. 面向对象六大原则详解

    本文来说下面向对象六大原则 文章目录 概述 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 开闭原则 六大原则总结 概述 这是设计模式系列开篇的第一篇文章.也是我学习设计模式过程中 ...

  2. 设计模式六大原则之里氏替换原则、依赖倒置原则详解

    设计模式六大原则--里氏替换原则.依赖倒置原则详解 1.里氏代换原则(Liskov Substitution Principle) 概念 顾名思义,该原则用于经常发生替换的地方,在Java中指的是实现 ...

  3. 设计模式六大原则及常用模式详解

    设计模式六大原则 1.单一职责原则(Single Responsibility Principle) 定义 : 应该有且只有一个原因引起类的变化 注意 : 这里的类不光指类,也适用于方法和接口,比如我 ...

  4. 设计模式-软件架构设计七大原则及开闭原则详解

    前言 在日常工作中,我们使用Java语言进行业务开发的时候,或多或少的都会涉及到设计模式,而运用好设计模式对于我而言,又是一个比较大的难题.为了解决.克服这个难题,Remi酱特别开了这个博客来记录自己 ...

  5. java connection 单例_Java设计模式之单例模式详解

    Java设计模式之单例模式详解 什么是设计模式 设计模式是在大量的实践中总结和理论之后优选的代码结构,编程风格,以及解决问题的思考方式.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可 ...

  6. PHP 设计模式六大原则

    http://www.cnblogs.com/yujon/p/5536118.html 设计模式六大原则(1):单一职责原则 不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责 设计模 ...

  7. Java 设计模式六大原则

    Java 设计模式六大原则 单一职责原则 定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责. 问题由来:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而 ...

  8. 快速理解设计模式六大原则

    设计模式的核心总结起来就一句话:用抽象构建框架,用实现扩展细节.目的就是代码修改的改动量最小 设计模式六大原则 单一职责原则 很好理解,一个类职责要单一,不要承载过多的职责,就比如说我们电脑上所有的文 ...

  9. 子慕谈设计模式系列(二)——设计模式六大原则

    六大原则 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 开闭原则 前言 设计模式不容易用文字描述清楚,而过多的代码,看起来也让人摸不到头脑,加上词语或者文字描述的抽象感,很容易让 ...

  10. 设计模式六大原则——合成/聚合复用原则(CARP)

    1.定义 简而言之,对于合成/聚合复用原则的定义就是:要尽量使用合成和聚合,尽量不要使用继承. 2.释义 为什么"要尽量使用合成和聚合,尽量不要使用继承"呢? 这是因为: 第一,继 ...

最新文章

  1. zabbix如何配置微信报警
  2. 微型计算机硬件及其应用,《微型计算机硬件软件及其应用例题习题集》.pdf
  3. SBO业务单据类型(总结)
  4. 【VB.NET】VB.NET数据库技术问题的解答
  5. Spring-自定义类实现AOP(八)
  6. 【华为云技术分享】MongoDB经典故障系列三:副本集延迟太高怎么办?
  7. C#正则的委托和lambda表达式用法
  8. 原子变量, 无锁定且无等待算法
  9. java创建线程的两种方法是_java创建线程的两种方法
  10. 串行总线 —— I2C、UART、SPI
  11. C# 设计模式 (一)
  12. javaIO流-File类及其方法
  13. maven集成tomcat7
  14. asm bin hex elf文件区别
  15. SDRAM控制器(初始化)
  16. 拼多多商家刚开店,哪些行为不能做?
  17. Linux 文本处理工具——sed
  18. 一文读懂LiveData 粘性事件
  19. 共享一个计算属相年份的咚咚-----javascript 代码
  20. OpenCV4萌新之路——详解图像读取函数 “imread”

热门文章

  1. 矩阵分析:三角分解,QR分解,秩分解,奇异值分解
  2. 爬取股票收盘价,计算神奇九转
  3. html5 视频缩略图,应用canvas获取video的缩略图
  4. 【WEB 工具汇总】
  5. 计算机怎么不读u盘,老司机告诉你电脑不读U盘的解决方法
  6. 清净,一键关闭淘宝、京东营销垃圾短信
  7. ux设计_UX设计趋势回顾展2019
  8. VBA-EXCEL:控制WORD文件
  9. WebPack+React.Js+BootStrap 实现进制转换工具
  10. 解决“用友U8输入中文汉字显示问号“的问题