开发中适当的使用设计模式,可以让项目有更易扩展,易维护、低耦合,代码简洁等
单例模式
<?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 // 他们都说土