六大原则
Contents
单一原则
一个类或者一个方法只负责一项职责。
例子
用户登录:用户可以用密码登录、微信登录、短信验证码登录
错误示范
class User {
public function login($type)
{
if ($type === 'password') {
print_r('密码登录');
} else if ($type === 'wechat') {
print_r('微信登录');
} else if ($type === 'sms') {
print_r('短信登录');
}
}
}
正确示范
class User {
public function loginByPassword()
{
print_r('密码登录');
}
public function loginByWechat()
{
print_r('微信登录');
}
public function loginBySms()
{
print_r('短信登录');
}
}
里式替换原则
子类可以扩展父类的功能,但不能改变原有父类的功能。子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
例子
缓存:redis缓存、memcache缓存。
错误示范
class Cache
{
public function set($key, $value)
{
print_r('缓存');
}
}
class Redisextends Cache
{
public function set($key, $value)
{
print_r('Redis缓存');
}
}
class Memcache extends Cache
{
public function set($key, $value)
{
print_r('memcache缓存');
}
}
正确示范
abstract class Cache
{
abstract public function set($key, $value);
}
class Redisextends Cache
{
public function set($key, $value)
{
print_r('Redis缓存');
}
}
class Memcache extends Cache
{
public function set($key, $value)
{
print_r('memcache缓存');
}
}
依赖倒置原则
模块之间的依赖通过抽象发生,实现类之间不直接发生依赖关系,而是通过接口或抽象类产生。
例子
用户抽奖活动:随机抽奖,权重抽奖。
错误示范
// 用户类
class User
{
}
// 抽奖逻辑类
class Draw
{
// 随机抽奖
public function byRand(User$user)
{
}
// 权重抽奖
public function byWeight(User $user)
{
}
}
正确示范
// 用户类
class User
{
}
interface IDraw
{
public function handle(User $user);
}
// 随机抽奖类
class DrawRand implements IDraw
{
public function handle(User $user)
{
}
}
// 权重抽奖
class DrawWeight implements IDraw
{
public function handle(User $user) {
}
}
// 抽奖逻辑类
class DrawControl {
// 抽奖
public function doDraw(IDraw $draw, User $user)
{
}
}
接口隔离原则
一个类对另一个类的依赖应该建立在最小的接口上,要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口。类不应该依赖它不需要的接口。
错误示范
// 动物接口
interface Animal
{
// 可以跑
abstract public function run();
// 可以飞
abstract public function fly();
}
class Dog implements Animal
{
public function run()
{
print_r('dog run');
}
public function fly()
{
print_r('dog cant not fly');
}
}
class Bird implements Animal
{
public function run()
{
print_r('run');
}
public function fly()
{
print_r('fly');
}
}
如上例子,狗不需要 fly。
正确示范
interface IRun
{
abstract public function run();
}
interface IFly
{
abstract public function fly();
}
class Dog implements IRun
{
public function run()
{
print_r('run');
}
}
class Bird implements IFly
{
public function fly()
{
print_r('fly');
}
}
迪米特原则
最少知道原则,尽量降低类与类之间的藕合
例子
老师负责具体某一个学生的学习情况,校长关心老师所在班级的总体成绩,不会过问具体某一个学生的学习情况。
错误示范
class Student
{
}
class Teacher
{
public Student $students;
}
class Principal
{
public function total()
{
$teacher = new Teacher();
$teacher->students;
// 然后计算
}
}
正确示范
class Student
{
}
class Teacher
{
public Student $students;
public function total()
{
this->students;
// 然后计算
}
}
class Principal
{
public function total()
{
$teacher = new Teacher();
$teacher->total();
}
}
开闭原则
软件设计中的对象、类、模块和函数对扩展应该是开放的,但对于修改是封闭的。开闭
例子
酒店价格,根据不同的用户给不同的价格,普通用户全价,vip9折。
错误示范
class Hotel
{
public function getPrice($userLevel)
{
if ($userLevel === 'ordinary') {
print_r('全价');
} else if ($userLevel === 'vip') {
print_r('九折');
}
}
}
如果需求变更,加上一个超级vip用户打八折,就需要修改 getPrice 方法了。
正确示范
interface IRoomPrice
{
abstract public function getPrice();
}
class Ordinary implements IRoomPrice
{
public function getPrice()
{
print_r('全价');
}
}
class Vip implements IRoomPrice
{
public function getPrice()
{
print_r('九折');
}
}
class SuperVip implements IRoomPrice
{
public function getPrice()
{
print_r('八折');
}
}