• PHP常用设计模式讲解


    开发中适当的使用设计模式,可以让项目有更易扩展,易维护、低耦合,代码简洁等

    单例模式

    <?php
    
    /**
     * 单例模式:使类在全局范围内只允许创建一个对象,常用于数据库连接等
     */
    
    class Singleton
    {
        // 必须用private修饰,防止被外部访问
        private static $_instance = null;
    
        private function __construct()
        {
            // 必须用private修饰,防止被实例化
        }
    
        private function __clone()
        {
            // 必须用private修饰 防止被克隆
        }
    
        public static function getInstance()
        {
            if (empty(self::$_instance)) {
                self::$_instance = new self();
            }
    
            return self::$_instance;
        }
    
        public function show()
        {
            echo '单例模式';
        }
    }
    
    $single = Singleton::getInstance();
    
    $single->show();
    // 单例模式

    工厂模式

    <?php
    
    /**
     * 工厂模式:统一了调用对象的方式,不必要在代码需要的地方 new 一个对象
     *           避免当改变某个类的名字或者方法之后,在调用这个类的所有的代码中都修改它的名字或者参数。
     *           当一个类的名称修改后,只需要在工厂方法里修改对应的名称即可。
     */
    
    class Database
    {
        public function connect()
        {
            echo '数据库连接成功';
        }
    }
    
    class Cache
    {
        public function connect()
        {
            echo '缓存开启成功';
        }
    }
    
    // 工厂模式
    class Factory
    {
        public static function getDatabase()
        {
            // 当Database类名称修改后,只需要需改此处代码
            return new Database();
        }
    
        public static function getCache()
        {
            // 当Cache类名称修改后,只需要需改此处代码
            return new Cache();
        }
    }
    
    Factory::getDatabase()->connect();
    // 数据库连接成功
    
    Factory::getCache()->connect();
    // 缓存开启成功

    注册模式

    <?php
    
    /**
     * 注册模式:解决全局共享对象问题
     *           将已经创建好的对象,挂到全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可,无需重新实例化
     *           tp5 框架中已体现
     */
    
    class Register
    {
        // 存储对象
        private static $_objects = [];
    
        // 设置对象
        public static function set($name, $object)
        {
            self::$_objects[$name] = $object;
        }
    
        // 获取对象
        public static function get($name)
        {
            return isset(self::$_objects[$name]) ? self::$_objects[$name] : null;
        }
    
        // 删除对象
        public static function delete($name)
        {
            unset(self::$_objects[$name]);
        }
    }
    
    $object = new Stdclass();
    
    // 存储对象
    Register::set('stdClass', $object);
    
    // 获取对象
    $object = Register::get('stdClass');
    
    // $object->func() 调用对象方法

    观察者模式

    <?php
    
    /**
     * 观察者模式:当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新。
     *             当一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理的逻辑。
     *             当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码。
     *             观察者模式实现了低耦合,非侵入式的通知与更新机制
     */
    
    // 观察者
    interface Observer
    {
        public function update();
    }
    
    class Message implements Observer
    {
        public function update()
        {
            // todo push message to user
            echo '给用户推送消息通知'. PHP_EOL;
        }
    }
    
    class Sms implements Observer
    {
        public function update()
        {
            // todo push sms to user
            echo '给用户发送短信通知' . PHP_EOL;
        }
    }
    
    // 生产者
    class OrderHandle
    {
        private $_observers = [];
    
        /**
         * 添加观察者
         * @param Observer $observer
         */
        public function setObserver(Observer $observer)
        {
            $this->_observers[] = $observer;
        }
    
        public function start()
        {
            echo '订单处理开始' . PHP_EOL;
        }
    
        public function complete()
        {
            $this->notify();
            echo '订单处理完成' . PHP_EOL;
        }
    
        /**
         * 通知消费者
         */
        private function notify()
        {
            foreach ($this->_observers as $observer) {
                $observer->update();
            }
        }
    }
    
    $orderHandle = new OrderHandle();
    
    $orderHandle->setObserver(new Message());
    $orderHandle->setObserver(new Sms());
    
    $orderHandle->start();
    $orderHandle->complete();
    // 订单处理开始
    // 给用户推送消息通知
    // 给用户发送短信通知
    // 订单处理完成

    策略模式

    <?php
    
    /**
     * 策略模式:将一组特定的行为和算法封装成类,以适应某些特定的上下文环境
     *           应用:社区中,根据用户性别,在广告位中展示不同的广告,男性、女性。
     */
    
    interface Strategy
    {
        public function showAd();
    }
    
    // 男性策略
    class MaleStrategy implements Strategy
    {
        public function showAd()
        {
            echo 'T恤,衬衫,运动裤';
        }
    }
    
    // 女性策略
    class FemaleStrategy implements Strategy
    {
        public function showAd()
        {
            echo '马甲,牛仔,连衣裙';
        }
    }
    
    // 用户信息
    class User
    {
        private $_strategy;
    
        public function setStrategy(Strategy $strategy)
        {
            $this->_strategy = $strategy;
        }
    
        public function showAd()
        {
            $this->_strategy->showAd();
        }
    }
    
    $gender = isset($_GET['gender']) ? $_GET['gender'] : 'male';
    $user = new User();
    
    if ($gender === 'female') {
        $strategy = new FemaleStrategy();
    } else {
        $strategy = new MaleStrategy();
    }
    
    $user->setStrategy($strategy);
    $user->showAd();
    // T恤,衬衫,运动裤

    适配器模式

    <?php
    
    /**
     * 适配器模式:将作用相同的不同类的不同方法封装成统一的API,对外只提供这一份api,而不管内部实现
     *             数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一致的API
     *             类似的还有Cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致的API
     */
    
    interface IDatabase
    {
        public function connect($host, $user, $password, $database);
        public function query();
    }
    
    // 自定义mysqli 避免与系统冲突
    class IMysqli implements IDatabase
    {
        protected $_connect = null;
    
        // 数据库链接
        public function connect($host, $user, $password, $database)
        {
            $mysqli = new mysqli($host, $user, $password, $database);
    
            if ($mysqli->connect_error) {
                die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
            }
    
            $this->_connect = $mysqli;
        }
    
        public function query()
        {
            $this->_connect->query("delete from user WHERE id = 2");
        }
    }
    
    // 自定义pdo 避免与系统冲突
    class IPdo implements IDatabase
    {
        protected $_connect = null;
    
        // 数据库链接
        public function connect($host, $user, $password, $database)
        {
            $dsn = "mysql:host={$host};dbname={$database}";
    
            try {
                $pdo = new PDO($dsn, $user, $password);
            } catch (PDOException $e) {
                die('Connection Error: ' . $e->getMessage());
            }
    
            $this->_connect = $pdo;
        }
    
        public function query()
        {
            $this->_connect->exec("delete from user WHERE id = 1");
        }
    }
    
    // 数据库对外提供连接的类
    class Db
    {
        protected $_connect = null;
    
        public function connect($connectType)
        {
            if ($connectType === 'mysqli') {
                $this->_connect = new IMysqli();
            } else if ($connectType === 'pdo') {
                $this->_connect = new IPdo();
            }
    
            return $this->_connect;
        }
    }
    
    // 系统配置采用哪种连接方式
    $databaseType = 'pdo';
    $db = (new Db())->connect($databaseType);
    
    $db->connect('127.0.0.1', 'root', '123456', 'database');
    
    // 统一查询方法,不需要关心它内部是用query实现,还是用exec 实现
    $db->query();

    装饰器模式

    <?php
    
    /**
     * 装饰器模式:实现对类的动态添加或修改类功能
     *             如果要在一个类中修改并添加额外的功能,通常需要一个子类来继承并重写类的方法
     *             使用装饰器模式,仅需要在运行时添加一个装饰器对象即可实现,可以实现最大额灵活性。
     */
    
    interface Decorator
    {
        // 穿着
        public function wear();
    }
    
    class Clothes implements Decorator
    {
        public function wear()
        {
            echo '身穿牛仔配T恤';
        }
    }
    
    class Shoe implements Decorator
    {
        public function wear()
        {
            echo '脚踏詹15';
        }
    }
    
    class Hat implements Decorator
    {
        public function wear()
        {
            echo '头戴New York';
        }
    }
    
    // 被装饰类
    class Person
    {
        protected $_decorator = [];
    
        public function setDecorator(Decorator $decorator)
        {
            $this->_decorator[] = $decorator;
        }
    
        public function display()
        {
            echo '我的行头:';
    
            foreach ($this->_decorator as $decorator) {
                $decorator->wear();
            }
    
            echo '他们都说土';
        }
    }
    
    $person = new Person();
    
    // 装饰衣服、鞋子、帽子,而不需要对person类进行重写,灵活搭配
    $person->setDecorator(new Clothes());
    $person->setDecorator(new Shoe());
    $person->setDecorator(new Hat());
    
    $person->display();
    // 我的行头:
    // 身穿牛仔配T恤
    // 脚踏詹15
    // 头戴New York
    // 他们都说土

  • 相关阅读:
    【每日一题】16.Treepath (LCA + DP)
    M-SOLUTIONS Programming Contest 2020 游记 (AB水题,CD模拟,E题DFS)
    关于“Github上传以及Clone时发生的 Failed to connect to github.com port 443: Timed out 问题解法记录
    【离散数学】学习笔记目录
    【每日一题】15.Xorto (前缀和枚举)
    【动态规划】动态规划基础 (OI wiki)
    【每日一题】14.Accumulation Degree(树形DP + 二次扫描)
    AtCoder Beginner Contest 199 游记(AB水题,C字符串操作,D搜索,E状压)
    JXUST_NC
    LinkedList源码阅读笔记
  • 原文地址:https://www.cnblogs.com/cqingt/p/8809556.html
Copyright © 2020-2023  润新知