解释:顾名思义,就是一个类只负责一个职责
优点:
1、代码的粒度降低了,类的复杂度降低了。
2、可读性提高了,每个类的职责都很明确,可读性自然更好。
3、可维护性提高了,可读性提高了,一旦出现 bug ,自然更容易找到他问题所在。
4、改动代码所消耗的资源降低了,更改的风险也降低了。
例如:以下代码场景中需要创建鱼移动方式就会出现问题
/** * 动物类 * Class Animal * @package app\api\controller */ class Animal{ /** * 移动方式 * @param $animal * @return string */ public function move($animal): string { return $animal."会爬行"; } } //使用场景 $animal = new Animal(); echo $animal->move("蜘蛛"); /**比如现在有一条鱼 那么就不是爬行因此不能调用$animal->move("鱼");*/
根据上面情况可以使用单一职责原则修改如下
/**单一职责具体修正如下*/ /** * 陆地生物类 * Class Land * @package app\api\controller */ Class Land{ /** * 移动方式 * @param $animal * @return string */ public function move($animal): string { return $animal."会爬行"; } } /** * 海洋生物类 * Class Ocean * @package app\api\controller */ Class Ocean{ /** * 移动方式 * @param $animal * @return string */ public function move($animal): string { return $animal."会游泳"; } } /**使用场景*/ $animal = new Land(); echo $animal->move("蜘蛛"); $ocean = new Ocean(); echo $ocean->move("鱼");
解释:在子类中尽量不要重写和重载父类的方法
优点:增强程序的健壮性,版本升级是也可以保持非常好的兼容性.即使增加子类,原有的子类还可以继续运行.在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑
例如下面示例中Operation2类add函数违背里氏替换原则不应该重写父类函数,应该采用抽象方法
//里氏替换原则 Class Operation1{ public function add($a, $b) { return $a+$b; } } Class Operation2 extends Operation1 { public function add($a, $b) { return $a+$b+3; } }
根据上面情况可以使用里氏替换原则修改如下
/**里氏替换原则修正如下*/ abstract Class Operation{ public abstract function add($a,$b); } Class Add extends Operation { public function add($a, $b) { return $a+$b; } } Class Add2 extends Operation{ public function add($a, $b) { return $a+$b+2; } }
解释:上层模块不应该依赖底层模块,它们都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象
优点:采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性
例如以下示例中当我们需要阅读ipad的时候就不能通过Read类的read函数实现
/** * 书籍类 * Class Book * @package app\api\controller */ Class Book{ public function getContent() { return "book"; } } /** * 阅读类 * Class Read * @package app\api\controller */ Class Read{ public function read(Book $book) { return $book->getContent(); } } //阅读书 (new Read)->read(new Book());
根据上面情况可以使用依赖倒置原则修改如下
/** * 读取内容接口 * Interface ReadInterface * @package app\api\controller */ interface ReadInterface{ public function getContent(); } /** * 书籍类 * Class Book * @package app\api\controller */ Class Book implements ReadInterface { public function getContent() { return "book"; } } /** * Ipad类 * Class Ipad * @package app\api\controller */ Class Ipad implements ReadInterface { public function getContent() { return "ipad"; } } /** * 阅读类 * Class Read * @package app\api\controller */ Class Read{ public function read(ReadInterface $book) { return $book->getContent(); } } //这样就可以使用Read类的read函数使用Ipad类 (new Read)->read(new Book()); (new Read)->read(new Ipad());
解释:客户端不应该依赖它不需要的接口。类间的依赖关系应该建立在最小的接口上
优点:
例如以下示例中
interface Base{ public function func1(); public function func2(); } Class A implements Base{ public function func1() { return "A1"; } public function func2() { //此类中并未使用该方法 } } Class B implements Base{ public function func1() { //此类中并未使用该方法 } public function func2() { return "B2"; } }
接口隔离原则修改后如下
interface BaseA{ public function func1(); } interface BaseB{ public function func2(); } Class A implements BaseA{ public function func1() { return "A1"; } } Class B implements BaseB{ public function func2() { return "B2"; } }
解释:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性
优点:
例如以下示例中
Class C{ function a() { $a = 10; $a += 100; return $a; } } Class D{ function d(C $c) { $d = 100; $a = $c->a(); //$a变量从C类中a方法中获取后还对$a进行操作 $a = $a*10; $d +=$a; return $d; } }
Class C{ function a() { $a = 10; $a += 100; $a = $a*10; return $a; } } Class D{ function d(C $c) { $d = 100; $a = $c->a(); //此处迁移到C类中a方法 //$a = $a*10; $d +=$a; return $d; } }
解释:类、模块和函数应该对扩展开放,对修改关闭