设计模式

一、设计模式的概念

设计模式:针对特定的问题提出的一中解决方案,和平台、语言无关。
作用:

  1. 更好的理解面向对象的思想
  2. 使我们的代码更加的优雅
  3. 使我们的代码更加容易扩展和复用

    面向对象的一些原则:

  4. 高内聚、低耦合

  5. 对扩展开放,对修改封闭(开闭原则)
  6. 单一职责(一个类的功能应该单一)

二、常见的设计模式

单例

单例就是一个类只实例化一个对象
写法:

  1. 私有的构造
  2. 私有的克隆
  3. 私有的静态属性
  4. 公有的静态方法
class Dog
{
    //5 私有的对象成员
    protected static $dog;

    //1. 把构造函数私有化
    protected function __construct()
    {}
    //2 把clone私有化
    protected function __clone()
    {}
    //3 反序列化方法__wakeup私有化
    protected function __wakeup()
    {}

    //4 自己定义公有的方法产生对象
    public static function getInstance()
    {
        // 如果没有创建对象,self::$dog为空,则创建对象
        if (self::$dog == null) {
            self::$dog = new self();
        }

        return self::$dog;
    }
}

$dog1 = Dog::getInstance();  //new Dog();

使用场景
应用只启动一次,连接数据库等耗费资源的类都可以考虑使用单例

简单工厂

把客户端代码和类隔离,统一了对象的创建,修改了类不会影响到客户端的代码

abstract class Calculator implements IOperating
{
    public $num1;
    public $num2;
    public abstract function operate();
}
class Add  extends Calculator
{
    public  function operate()
    {
        return $this->num1 + $this->num2;
    }
}

//核心类
class SimpleFactory
{
    public static function create($operator)
    {
        switch($operator)
        {
            case '+':
                return new Add();
                break;
            case '-':
                break;
        }
    }
}

// 客户端代码
//所有对象的创建,都通过工厂
$obj = SimpleFactory::create('+');
$obj->num1 = 10;
$obj->num2 = 20;
echo $obj->operate();

工厂方法

与简单工厂不同,工厂类不再创建对象,把实例化对象的任务交给了子类
优点:解决了工厂不容易扩展的缺陷
缺点:客户端的代码负载

abstract class Calculator
{
    public $num1;
    public $num2;
    public abstract function operate();
}
class Add  extends Calculator
{
    public  function operate()
    {
        return $this->num1 + $this->num2;
    }
}
class Sub  extends Calculator
{
    public  function operate()
    {
        return $this->num1 - $this->num2;
    }
}

//改进
class SimpleFactory
{
    public static function create($className)
    {
        return new $className();
    }
}

//客户端代码
//所有对象的创建,都通过工厂
$addObj = AddFactory::create();
$addObj->operate();

SimpleFactory::create('Add');

观察者模式

  • 一个对象观察另一个对象,当被观察对象的状态发生变化时,观察者对象可以收到通知做出相应的改变。观察者模式提供了解耦观察者和被观察者两个类之间的解耦。
  • 适用于:一个对象发生改变时,通知另外依赖它的对象,依赖对象做相应的改变
interface AbstractObserver
{
    public function upate($info=null);//通知的消息
}



class Student implements AbstractObserver  
{
    public function update($info = null)
    {
        echo "好好学习<br/>";
    }
}

//抽象的被观察者
interface AbstractSubject
{
    public function attach(AbstractObserver $obserer);
    public function detach(AbstractObserver $obserer);
    public function notify();
}


//被观察者
class Subject implements AbstractSubject
{
    protected $obserers = [];

    public function __construct()
    {

    }
    //添加观察者
    public function attach(AbstractObserver $obserer)
    {
        $this->obserers[] = $obserer;
    }
    //删除观察者
    public function detach(AbstractObserver $obserer)
    {
        //返回键值
        $key = array_search($obserer, $this->obserers);
        if ($key !== false) {
            unset($this->obserers[$key]);
        }
    }

    //通知观察者
    public function notify()
    {
        foreach ($this->obserers as $key => $value) {
            $value->update();//通知
        }

    }
}

适配器模式

可以将一个系统的接口转换成客户希望的接口,使得原本不兼容系统可以一块工作
使用场景:

  • 使用了一个接口经常会发生变化的第三方库
  • 旧系统的接口和新系统的不兼容,但旧系统比较复杂,不容易修改
//服务器端提供json
//{'name':'tom','age':18,'sex':'男'} json
//['name'=>'tom','age'=>18,'sex'=>'男']
class Server
{
    public function json()
    {
        return json_encode(['name'=>'tom','age'=>18,'sex'=>'男']);
    }
}
//需要转换的接口方法
interface IAdaper
{
    //转换方法
    public function json2Aarray();
}

//适配器类
class Adapter implements IAdaper
{
    //1 包含一个server对象
    protected $server;
    public function __construct($server)
    {
        $this->server = $server;
    }

    //2 实现接口方法
    public function json2Aarray()
    {
        var_dump($this->server->json());
        //将json串转换为数组,第二个参数必须为true
        return json_decode($this->server->json(),true);
    }
}


//客户端代码
class Client
{
    public function test($data)
    {
        foreach ($data as $key => $value) {
            var_dump($value);
        }
    }
}


//客户端代码
$server = new Server();

//转换器
$adapter = new Adapter($server);
//客户端
$client = new Client();
var_dump($adapter->json2Aarray());
$client->test($adapter->json2Aarray());

策略模式

在不同情况会使用不同算法,要解耦算法对对象的影响,可以使用策略模式

//策略模式
interface ISalary
{
    public function computeSalary();//计算工资的方法
}

class Manager implements ISalary
{
    public function computeSalary()
    {
        echo "基本工资+补贴+效益<br/>";
    }
}

class Teacher implements ISalary
{
    public function computeSalary()
    {
        echo "基本工资+补贴<br/>";
    }
}

//环境类
class Context
{
    protected $strategy;//策略

    //1 设置策略
    public function setStrategy(ISalary $strategy)
    {
        $this->strategy = $strategy;
    }

    //调用对象实现策略
    public function compute()
    {
        $this->strategy->computeSalary();
    }
}

//客户端代码
$teacher = new Teacher();
$manager = new Manager();

$context = new Context();
$context->setStrategy($teacher);
$context->compute();

门面设计模式

使用场景:

  • 给复杂的子系统提供一个简单的接口
  • 提高子系统的独立性
    优点:

  • 对客户屏蔽了子系统,因此减少了客户处理对象的数目,并且使得子系统使用起来更加方便

  • 实现了子系统与客户之间的松耦合关系
//门面设计模式
class SystemA
{
    public function demo1()
    {
        echo "A:demo1<br/>";
    }
}

class SystemB
{
    public function demo2()
    {
        echo "B:demo2<br/>";
    }
}
class SystemC
{
    public function demo3()
    {
        echo "C:demo3<br/>";
    }
}


class Facade
{
    protected $systemA;
    protected $systemB;
    protected $systemC;

    public function __construct()
    {
        $this->systemA = new SystemA();
        $this->systemB = new SystemB();
        $this->systemC = new SystemC();
    }

    //新接口
    public function demo()
    {
        $this->systemA->demo1();
        $this->systemB->demo2();
        $this->systemC->demo3();
    }
}

依赖注入/控制反转(DI)

依赖注入(Dependency Injection)
控制反转(Inversion of Control)
当一个类的实例需要另一个类的实例协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。而采用依赖注入的方式,创建被调用者的工作不再由调用者来完成,因此叫控制反转,创建被调用者的实例的工作由IOC容器来完成,然后注入调用者,因此也称为依赖注入。

interface IRunning
{
    public function run();//交通工具的运行方式
}

class Bus implements IRunning
{
    public function run()
    {
        echo "坐公交";
    }
}

class Ofo implements IRunning
{
    public function run()
    {
        echo "骑自行车";
    }
}

class Person
{
    public $name;
    public function __construct($name)
    {
        $this->name = $name;
    }

    public function goHome($tool)//person依赖于注入的对象
    {

        echo $this->name;
        $tool->run();
        echo "回家<br/>";
    }
}

$wzy = new Person('Tom');
$wzy->goHome(new Bus());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值