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('八折');
     }
}