PHP DIY 系列------框架篇:9. 设计模式 
                                                    
                        
                    
                    
  
                    
                    框架的开发基本结束了,这一节我们来探讨一下设计模式。
谈设计模式,首先要来简单聊聊面向对象。
面向对象
面向对象程序设计(Object-Oriented Programming, OOP)是一种程序设计范型,同时也是一种程序开发方法。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和可扩展性。它和面向过程、函数式编程被称为编程语言中的三大范式。
概念知识
- 面向对象的核心思想是对象、封装、可重用性、可扩展性。
 - 面向对象三要素:封装、继承和多态。
 - 面向对象设计的五大原则:单一职责原则、接口隔离原则、开放封闭原则、替换原则、依赖倒置原则。
 
关于这些概念的更详细解释,我推荐大家阅读《PHP核心技术与最佳实践》这本书关于关于面向对象的部分。
设计模式
上述所述的面向对象知识,尤其是面向对象设计的五大原则,是诸多设计模式的基础。
设计模式有很多,我们可以简单列出来:
- 有强调实例化过程的创建型设计模式
 
- 抽象工厂
 - 生成器
 - 工厂方法
 - 原型
 - 单例
 
- 又有组合对象和类构成更大结构的结构型设计模式
 
- 适配器模式
 - 桥接模式
 - 组合模式
 - 装饰器模式
 - 外观模式
 - 享元模式
 - 代理模式
 
- 还有行为型设计模式
 
- 职责链模式
 - 命令模式
 - 解释器模式
 - 迭代器模式
 - 中介者模式
 - 备忘录模式
 - 观察者模式
 - 状态模式
 - 策略模式
 - 模板授权模式
 - 访问者模式
 
说到这里你有没有蒙圈?
其实我们无需一下子去了解那么多设计模式,在实际开发过程中我们可能也是混合使用设计模式的。我们不妨可以就框架里用到的几个典型的设计模式做一些分析。
单例模式
是否还记得我们使用Redis代替Session那一节,我们就用到了单例模式。
我们来简化一下代码:
class RedisSession
{
    private $redis;
    private function getRedisInstance()
    {
        if (empty($this->redis)) {
            $redis = new \Redis();
            $redis->connect($this->_config['host'], $this->_config['port'], $this->_config['timeout']);
            if (!$this->_config['auth']) {
                $redis->auth($this->_config['auth']);
            }
            $this->redis = $redis;
        }
        return $this->redis;
    }
}
一般我们还会在类里面加入一个魔术方法__clone,防止实例创建后被clone
单例模式有显而易见的优点:提高可重用性,减少开销。框架里使用Redis时都可以使用此方法来获取redis,也减少redis的连接数和多次连接时间。
策略模式
还记得依赖注入那一节么,我们举例的那个Travel就是一个很好的策略模式Demo:
interface Travel
{
    public function travelAlgorithm();
}
/**
 *具体策略类(ConcreteStrategy)
 *1:乘坐飞机
 */
class AirPlanelStrategy implements Travel
{
    public function travelAlgorithm()
    {
        echo"travelbyAirPlain\r\n";
    }
}
/**
 *具体策略类(ConcreteStrategy)
 *2:乘坐火车
 */
class TrainStrategy implements Travel
{
    public function travelAlgorithm()
    {
        echo"travelbyTrain\r\n";
    }
}
/**
 *
 *环境类(Context):
 *用一个ConcreteStrategy对象来配置。
 *维护一个对Travel对象的引用。可定义一个接口来让Strategy访问它的数据。
 *算法解决类,以提供客户选择使用何种解决方案:
 */
class PersonContext
{
    private $strategy = null;
    public function __construct(Travel $travel)
    {
        $this->strategy=$travel;
    }
    /**
     *旅行
     */
    public function travel()
    {
        return$this->strategy->travelAlgorithm();
    }
}
// 乘坐火车旅行
$person = new PersonContext(new TrainStrategy());
$person->travel();
// 改乘飞机
$person =PersonContext(new AirPlanelStrategy());
$person->travel();
策略模式降低了代码耦合度,可以使得我们下层代码依赖上层,替换下层代码即可简单实现功能的替换。
工厂方法
我们在路由解析创建控制器那里使用了工厂方法,只不过与路由解析代码糅合在一起,我们简化一下:
class Factory
{
    public function createController($controllerName)
    {
        $controllerName = rtrim($controllerName,'\\').'Controller';
        if (!class_exists($controllerName)) {
            throw new NotFoundException("未找到控制器");
        }
        return new $controllerName;
    }
    ···
}
工厂方法是很常见的一种设计模式,像Model经常能用到。
本作品采用《CC 协议》,转载必须注明作者和本文链接
          
          
          
                关于 LearnKu
              
                    
                    
                    
 
推荐文章: