一、常见的设计模式主要有23种,根据使用目标的不同可以分为以下三大类:创建设计模式、结构设计模式、行为模式
创建设计模式: (5种)
用于创建对象时的设计模式.初始化对象流程的设计模式.当程序复杂时,需要灵活创建对象,同时减少创建时的依赖.创建设计模式就是解决此问题的一类设计模式.
(1)单例模式
(2)工厂模式
(3)抽象工厂模式
(4)建造者模式
(5)原型模式
结构设计模式: (7种)
用于继承和接口时的设计模式.结构设计模式用于新类的函数方法设计,减少不必要的类定义,减少代码的冗余.
(1)适配器模式
(2)桥接模式
(3)合成模式
(4)装饰器模式
(5)门面模式
(6)代理模式
(7)享元模式
行为模式: (11种)
用于方法实现以及对应算法的设计模式,同时也是最复杂的设计模式.行为设计模式不仅仅用于定义类的函数行为,同时也用于不同类之间的协议、通信.
(1)策略模式
(2)模板方法模式
(3)观察者模式
(4)迭代器模式
(5)责任链模式
(6)命令模式
(7)备忘录模式
(8)状态模式
(9)访问者模式
(10)中介者模式
(11)解释器模式
二、按照范围分为: 类的设计模式,以及对象设计模式
类的设计模式:用于类的具体实现的设计模式.包含了如何设计和定义类,以及父类和子类的设计模式.
对象设计模式: 用于对象的设计模式.与类的设计模式不同,对象设计模式主要用于运行期对象的状态改变、动态行为变更等.
三、设计模式六大原则
开放封闭原则: 一个软件实体如类、模块和函数应该对扩展开放,对修改关闭.
里氏替换原则: 所有引用基类的地方必须能透明地使用其子类的对象.
依赖倒置原则: 高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象.
单一职责原则: 不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责.
接口隔离原则: 客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上.
迪米特法则: 一个对象应该对其他对象保持最少的了解.
单例模式
单例模式解决的是如何在整个项目中创建唯一对象实例的问题. (示例demo:)
1 <?php 2 //单例模式:保证某个类只有一个实例,能自行实例化对象,完成其所有的功能操作. 3 //最典型案例:数据库操作(单例模式可以避免大量的new操作.每一次new操作都会消耗系统和内存的资源.) 4 header("Content-Type: text/html;charset=utf-8"); 5 class User{ 6 //静态的私有属性(保存一个当前类的唯一对象) 7 private static $instance; 8 //私有的构造方法,防止类外new新对象 9 private function __construct(){ 10 } 11 //私有的克隆方法,防止类外克隆新对象 12 private function __clone(){ 13 14 } 15 //静态的公开方法,得到当前类的对象 16 public static function getInstance(){ 17 if(!self::$instance){ 18 self::$instance = new self(); 19 } 20 return self::$instance; 21 } 22 23 private $name; 24 public function setName($n){ 25 $this->name = $n; 26 } 27 public function getName(){ 28 echo $this->name; 29 } 30 31 } 32 $userA = User::getInstance(); 33 $userB = User::getInstance(); 34 echo '<pre>'.'单例模式获取唯一实例:'.'<br>'; 35 var_dump($userA,$userB); 36 37 echo '<hr>'.'单例模式获取当前类私有属性:'.'<br>'; 38 $userA->setName('admin_a'); 39 $userB->setName('admin_b'); 40 $userA->getName(); 41 echo '<br>'; 42 $userB->getName();
运行结果如下图:
工厂模式
工厂模式解决的是如何不通过new建立实例对象的方法. (示例demo)
1 <?php 2 //工厂模式:实例化对象模式,工厂方法代替new操作的一种设计模式. 3 //优点:避免当改变某个类的名字或者方法之后,调用这个类的所有的代码中都修改它的名字或者参数.(为系统结构提供灵活的动态扩展机制,减少了耦合) 4 //简单工厂模式生产对象 实例demo 5 interface People{ 6 public function sex(); 7 } 8 9 class Man implements People{ 10 public function sex(){ 11 echo 'this is Men'.'<br>'; 12 } 13 } 14 15 class Women implements People{ 16 public function sex(){ 17 echo 'this is Women'.'<br>'; 18 } 19 } 20 21 class Factoty{ 22 static function getObject($class_name){ 23 //可变类,生产新对象 24 return new $class_name; 25 } 26 } 27 28 $man = Factoty::getObject('Man'); 29 $man->sex(); 30 $woman = Factoty::getObject('Women'); 31 $woman->sex();
运行结果如下图:
观察者模式
当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新. (示例demo)
1 <?php 2 //观察者模式:某个对象可以被设置为是可观察的,只要通过某种方式允许其他对象注册为观察者.每当被观察的对象改变时,会发送信息给观察者 3 4 //获取类名和发送消息接口 5 interface IObserver{ 6 public function onSendMsg($msg); 7 public function getName(); 8 } 9 //添加可观察者接口 10 interface IObservable{ 11 //注意:$observer是个对象,需要保存到数组中 12 public function addObserver($observer); 13 } 14 15 class UserList implements IObservable{ 16 private $_observers = array(); 17 //添加观察者 18 public function addObserver($observer){ 19 $a=$this->_observers[]= $observer; 20 } 21 //移除观察者 (注意:其实就是移除对应的类) 22 public function removeObserver($observer_name) { 23 foreach($this->_observers as $index => $observer) { 24 if ($observer->getName() === $observer_name) { 25 //从数组中移除选定的元素 26 return array_splice($this->_observers, $index, 1); 27 } 28 } 29 } 30 //发送消息 31 public function sendMsg($msg){ 32 foreach($this->_observers as $v){ 33 $v->onSendMsg($msg); 34 } 35 } 36 } 37 38 class OneObserver implements IObserver{ 39 public function onSendMsg($args){ 40 echo($args.'=> send to OneObserver<br>'); 41 } 42 public function getName(){ 43 return 'OneObserver'; 44 } 45 } 46 47 class TwoObserver implements IObserver{ 48 public function onSendMsg($args){ 49 echo($args.'=> send to TwoObserver<br>'); 50 } 51 public function getName(){ 52 return 'TwoObserver'; 53 } 54 } 55 56 $ul = new UserList();//被观察者 57 $ul->addObserver(new OneObserver());//增加观察者 58 $ul->addObserver(new TwoObserver());//增加观察者 59 $ul->sendMsg('admin');//发送消息到观察者 60 $ul->removeObserver('OneObserver');//移除观察者 61 $ul->sendMsg("hello world");//发送消息到观察者
运行结果如下图:
策略模式
策略模式主要为了让客户类能够更好地使用某些算法而不需要知道其具体的实现. (示例demo)
1 <?php 2 interface Strategy { //抽象策略角色,以接口实现 3 public function do_method(); //算法接口 4 } 5 6 class ConcreteStrategyA implements Strategy { //具体策略角色A 7 public function do_method() { 8 echo 'do method A'; 9 } 10 } 11 12 class ConcreteStrategyB implements Strategy { //具体策略角色B 13 public function do_method() { 14 echo 'do method B'; 15 } 16 } 17 18 class ConcreteStrategyC implements Strategy { //具体策略角色C 19 public function do_method() { 20 echo 'do method C'; 21 } 22 } 23 24 class Question{ //环境角色 25 private $_strategy; 26 //初始化Strategy接口对应实现类 27 public function __construct(Strategy $strategy) { 28 $this->_strategy = $strategy; 29 } 30 public function handle_question() { 31 $this->_strategy->do_method(); 32 } 33 } 34 35 $strategyA = new ConcreteStrategyA(); 36 $question = new Question($strategyA); 37 $question->handle_question();//输出do method A 38 echo '<br>'; 39 $strategyB = new ConcreteStrategyB(); 40 $question = new Question($strategyB); 41 $question->handle_question();//输出do method B 42 echo '<br>'; 43 $strategyC = new ConcreteStrategyC(); 44 $question = new Question($strategyC); 45 $question->handle_question();//输出do method C
运行结果如下图:
命令模式
命令模式:在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。
但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。
在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式。
角色分析:
抽象命令: 定义命令的接口,声明执行的方法.
具体命令: 命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作.
命令接收者: 接收者,真正执行命令的对象.任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能.
控制者: 要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象.这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口. (示例demo)
1 <?php 2 interface Command { //命令角色 3 public function execute(); //执行方法 4 } 5 6 class ConcreteCommand implements Command { //具体命令方法 7 private $_receiver; 8 public function __construct(Receiver $receiver) { 9 $this->_receiver = $receiver; 10 } 11 //Command接口ConcreteCommand类实现对应Receiver类对应方法actionReceiver() 12 public function execute() { 13 $this->_receiver->actionReceiver(); 14 } 15 } 16 17 class Receiver { //接收者角色 18 private $_name; 19 public function __construct($name) { 20 $this->_name = $name; 21 } 22 public function actionReceiver() { 23 echo 'receive some cmd:'.$this->_name; 24 } 25 } 26 27 class Invoker { //请求者角色 28 private $_command; 29 public function __construct(Command $command) { 30 $this->_command = $command; 31 } 32 //Command接口ConcreteCommand类实现方法execute() 33 public function actionInvoker() { 34 $this->_command->execute(); 35 } 36 } 37 38 $receiver = new Receiver('hello world'); 39 $command = new ConcreteCommand($receiver); 40 $invoker = new Invoker($command); 41 $invoker->actionInvoker();//输出:receive some cmd:hello world
运行结果如下图: