PHP DIY系列–一起手写一个api框架
框架的开发基本结束了,这一节我们来探讨一下设计模式。
谈设计模式,首先要来简单聊聊面向对象。
面向对象
面向对象程序设计(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经常能用到。