类的设计原则

示意图

简介

SOLID:php

  • S: 单一职责原则 (SRP)
  • O: 开闭原则 (OCP)
  • L: 里氏替换原则 (LSP)
  • I: 接口隔离原则 (ISP)
  • D: 依赖反转原则 (DIP)
  • 迪米特法则

详情

单一职责原则(SRP:Single responsibility principle)

解耦和加强内聚性(高内聚,低耦合),一个类和方法的只负责一个职责html

  • 示例1:一个类中一个方法职责混乱。
class Activity {
  public function getActivity() {
    if ($this->startDate < time() && $this->endDate > time()) {
      return '活动:' . $this->name . '已经在' . date('Y-m-d H:i:s', $this->startDate) . '开始';
    } else {
      return '活动:' . $this->name . '没有开始';
    }
  }
}
复制代码

弊端:若是再增长条件,和输出修改,会加剧逻辑。 改变为 ->segmentfault

class Activity {
  public function getActivity() {
    return $this->isStart ? $this->getStartWord() : $this->getEndWord();
  }
  public function isStart() {
    return $this->startDate < time() && $this->endDate > time();
  }
  public function getStartWord() {
    return '活动:' . $this->name . '已经在' . date('Y-m-d H:i:s', $this->startDate) . '开始';  
  }
  public function getNotStartWord() {
    return '活动:' . $this->name . '没有开始';  
  }
}
复制代码
  • 示例2:类的职责混乱
class Activity {
  public function __construct(Activity $activity) {
    $this->activity = $activity;
  }
  public function draw() {
    if ($this->isStart()) {
      return $this->draw();
    }
    throw Exception('没有开始');
  }
}
复制代码

弊端:类的职责不清。抽奖和活动不该该属于同一个类 更改成->设计模式

class Activity {
  public function __construct(Activity $activity) {
    $this->activity = $activity;
    $this->config = '38_festival';
  }
  public function draw() {
    if ($this->isStart()) {
      return $this->initDrawManage->draw();
    }
    throw Exception('没有开始');
  }
  public function initDrawManage() {
    !isset($this->drawManage) && $this->drawManage = new DrawManage($this->config)
    return $this->drawManage
  }
}
class DrawManage {
  public function __construct($config) {
    $this->config = $config
  }
  public function draw() {
    ...
  }
}
复制代码

开闭原则(OCP:Open/Closed Principle)

对扩展开放,对修改关闭。 与其修改别人的代码(或者老代码)不如先继承,而后更改。ide

  • 示例1:新增一个学生,应当采用继承的方式来作,而不是修改原有的代码
interface UserInterface {
  public function getUserIdentify();
}
class User implements UserInterface {
  private $identify = '先生/女士';
  public function getUserIdentify {
    return $this->name . $this->identify;
  }
}
复制代码

改成->学习

interface UserInterface {
  public function getUserIdentify();
}
class User implements UserInterface {
  private $identify = '先生/女士';
  public function getUserIdentify {
    return $this->name . $this->identify;
  }
}
class Student extend User {
  private $identify = '学生';  
}
复制代码
  • 示例2:调整结构。 增长新的角色和工种时
interface UserInterface {
  public function getUserIdentify();
}
class User implements UserInterface {
  private $identify = 'young';
  public function getUserIdentify() {
    return $this->identify;
  }
}

class Student extend User {
  private $identify = 'student';  
}

class Work {
  private $identify

  public function __construct(UserInterface $identify) {
    $this->identify = $identify;
  }

  public function getWorking() {
    return $this->identify->getIdentify() == 'student'
    ? $this->study() : $this->working();
  }
  public function study() {
    return '学习';
  }
  public function wordking() {
    return '工做';
  }
}
复制代码

弊端:修改代码~~ 更改Work类的代码->优化

interface UserInterface {
  public function getUserIdentify();
  public function doing();
}
class User implements UserInterface {
  private $identify = 'young';
  public function getUserIdentify() {
    return $this->identify;
  }
  public function doing() {
    return 'working';
  }
}

class Student extend User {
  private $identify = 'student';
  public function doing() {
    return 'study';
  }
}

class Work {
  private $identify

  public function __construct(UserInterface $identify) {
    $this->identify = $identify;
  }

  public function getWorking() {
    return $this->identify->doing();
  }
}
复制代码

里氏替换原则(LSP:Liskov Substitution Principle)

父类出现的地方子类就能够出现,且替换成子类也不会出现任何错误或者异常。this

接口隔离原则 (ISP:Interface Segregation Principle)

针对接口的原则,规范以下:spa

  • 接口尽可能小(细化业务)
  • 接口高内聚(减小对外交互,public方法少)
  • 定制服务(应单独为一个个体服务)
  • 有限设计(和第一个规范相辅相成)

示例:.net

interface User {
  public function working();
  public function studing();
}
class Student implements User {
  public function working() {
    // 学生不工做(假设)
    return null;
  }
  ...
}
class Worker implements User {
  public fucntion studing
  {
    // 不学习(假设)
    return null;
  }
}
复制代码

能够修改->

interface StudentInterface {
  public function studing();
}
interface WorkerInterface {
  public function working();
}
class Student implements StudentInterface {
  ...
}
class Worker implements WorkerInterface {
  ...
}
复制代码

依赖反转原则 (DIP:Dependency Inversion Principle)

高层模块不该该依赖低层模块,两者都应该依赖其抽象;抽象不该该依赖细节;细节应该依赖抽象。

这个原则恰好本文的第二小节开闭原则示例1貌似就违反了,可是要看具体业务的,若是是A是父类,B是子类,具备必定的联系,没法分割就不遵循。若是A类和B类是平级关系,继承只是共用一些方法,那就有必要让二者都依赖抽象,便于该改动。

迪米特法则(Law of Demeter)

迪米特法则也叫作最少知识原则(Least Knowledge Principle,LKP),即一个对象应该对其余对象有最少的了解。不关心其余对象内部如何处理。

综述

根据实际状况使用不一样的原则,可使得程序下降耦合和冗余代码,优化程序。根据这些规则,会有一系列的设计模式,在实际使用时不必强行套用设计模式,须要根据业务实际划分合理便可。长城不是一天就能修好的~~~

参考

  1. www.cnblogs.com/HouJiao/p/5…
  2. segmentfault.com/a/119000001…
  3. blog.csdn.net/jhq0113/art…
相关文章
相关标签/搜索