设计模式是对典型问题的典型解决方案,是一种套路。比如说前端如何写选项卡,如何在网页弹窗,都是有固定套路的,前辈们都总结出来了,我们学会就好。
开发中所谓的“面向接口开发”,涉及到“调用”的概念。服务器端和客户端由不同的人员开发,但是不必要互相认识,开发的时候只需要对接口负责,就能够共同合作完成任务。生产插座的厂商和电器厂商并不是互相了解,但是只各自遵循插座插头规范,就能够做出可用的产品。
简单工厂
<?php //客户端和服务器端共同的接口 interface db{ function conn(); } //服务端开发,不知道将会被谁调用 class dbmysql implements db{ public function conn(){ echo '连接上了Mysql'; } } class dbsqlite implements db{ public function conn(){ echo '连接上了sqlite'; } } //简单工厂 class Factory{ public static function createDB($type){ if ($type=='mysql') { return new dbmysql(); } else if($type == 'sqlite'){ return new dbsqlite(); } else{ throw new Exception('错误的数据库类型'); } } } //客户端,不知道服务端到底有哪些类,只知道对方开放了一个Factory::createDB方法,并且方法允许传递数据库名称 $mysql = Factory::createDB('mysql'); $mysql->conn(); $sqlite = Factory::createDB('sqlite'); $sqlite->conn();
从上面的代码中可以看出来,如果服务端要新增一个oracle类型,根据开闭原则(对于修改是封闭的,对于扩展是开放的),在不修改服务端源代码的情况下,是不容易做到的。
工厂方法:
<?php //客户端和服务器端共同的接口 interface db{ function conn(); } interface Factory{ function createDB(); } //服务端开发,不知道将会被谁调用 class dbmysql implements db{ public function conn(){ echo '连接上了Mysql'; } } class dbsqlite implements db{ public function conn(){ echo '连接上了sqlite'; } } class mysqlFactory implements Factory{ public function createDB(){ return new dbmysql(); } } class sqliteFactory implements Factory{ public function createDB(){ return new dbsqlite(); } } //服务端添加oracle类 class dboracle implements db{ public function conn(){ echo '连接上了orecle'; } } class oracleFactory implements Factory{ public function createDB(){ return new dboracle(); } } //客户端开始 $fact = new mysqlFactory(); $db = $fact->createDB(); $db->conn(); $fact = new sqliteFactory(); $db = $fact->createDB(); $db->conn(); $fact = new oracleFactory(); $db = $fact->createDB(); $db->conn();
单例模式。当我们需要数据库对象,cookie对象或者upload对象的时候,通常需要用到单例模式。
实现思路:封闭外部的new操作,内部可以new,如果有,就直接返回,没有就new出来。最后再防止外部覆盖或者克隆。
<?php class single{ protected static $ins = null; public static function getIns(){ if (self::$ins === null) { self::$ins = new self(); } return self::$ins; } final protected function __construct(){ } final protected function __clone(){ } }
观察者模式
用javascript实现观察者模式
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>用观察者模式切换页面风格</title> <style> div{ float: left; width: 200px; height: 200px; margin: 10px; border: 1px solid black; } </style> <script> window.onload = function(){ //服务端 var oSwitch = document.getElementById('switch'); oSwitch.observers = {}; oSwitch.attach = function(key,obj){ this.observers[key] = obj; }; oSwitch.detach = function(key){ delete this.observers[key]; }; oSwitch.onchange = oSwitch.modify = function(){ //这里还是很关键的 for(var key in this.observers){ this.observers[key].update(this); } }; //客户端 var oColor = document.getElementById('color'); var oAd = document.getElementById('ad'); oColor.update = function(observe){ if (observe.value == 'male') { this.style.background = 'gray'; } else if(observe.value == 'female'){ this.style.background = 'pink'; } } oAd.update = function(observe){ if (observe.value == 'male') { this.innerHTML = '汽车'; } else if(observe.value == 'female'){ this.innerHTML = '化妆品'; } } //观察select的变化 oSwitch.attach('color',oColor); oSwitch.attach('ad',oAd); //如果要扩展hobby var oHobby = document.getElementById('hobby'); oHobby.update = function(observe){ if (observe.value == 'male') { this.innerHTML = '爱好是打篮球'; } else if(observe.value == 'female'){ this.innerHTML = '爱好是逛街'; } } //观察爱好 document.getElementById('confirm').onclick = function(){ oSwitch.attach('hobby',oHobby); }; document.getElementById('cancel').onclick = function(){ oSwitch.attach('hobby'); }; }; </script> </head> <body> <select name="" id="switch"> <option value="male">男士风格</option> <option value="female">女士风格</option> </select> <input type="button" value="观察爱好" id="confirm"> <input type="button" value="取消观察爱好" id="cancel"> <div id="color">我是颜色</div> <div id="ad">我是广告</div> <div id="hobby">我是爱好</div> </body> </html>
用php实现观察者模式
<?php //PHP5中提供了观察者observer与被观察者subject的接口 class user implements SplSubject{ public $times; public $hobby; protected $observers = null; public function __construct($hobby){ $this->times = rand(1,10); $this->hobby = $hobby; $this->observers = new SplObjectStorage(); } public function login(){ //操作session $this->notify(); } public function attach(SPLObserver $observer){ $this->observers->attach($observer); } public function detach(SPLObserver $observer){ $this->observers->detach($observer); } public function notify(){ $this->observers->rewind(); while ($this->observers->valid()) { $observer = $this->observers->current(); $observer->update($this); $this->observers->next(); } } } class security implements SPLObserver{ public function update(SplSubject $subject){ if ($subject->times < 3) { echo '这是第'.$subject->times.'次安全登陆'.'<br/>'; } else{ echo '这是第'.$subject->times.'次登陆,异常'.'<br/>'; } } } class ad implements SPLObserver{ public function update(SplSubject $subject){ if ($subject->hobby == 'sports') { echo '台球世锦赛'; } else{ echo '好好学习'; } } } //实施观察 $user = new user('sports'); $user->attach(new security()); $user->attach(new ad()); $user->login(); ?>
职责链模式