设计模式

来源:互联网 发布:魔兽争霸3 mac 编辑:程序博客网 时间:2024/06/05 09:21

一、设计模式的概念

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

  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());
原创粉丝点击