您的位置 首页 php

PHP常见的设计模式

设计模式六大原则

  • 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
  • 里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象.
  • 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
  • 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
  • 接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
  • 迪米特法则:一个对象应该对其他对象保持最少的了解。

1.单例设计模式(Singleton)

应用场景:

一个单例类应具备以下特点:

单例模式的例子:

<?php 
/** 
* Singleton of Database 
*/ 
class Database 
{ 
 // We need a static private variable to store a Database instance. 
 privatestatic $instance; 
 // Mark as private to prevent it from being instanced. 
 private function__construct() 
 { 
 // Do nothing. 
 } 
 private function__clone() 
 { 
 // Do nothing. 
 } 
 public static function  getInstance () 
 { 
 if (!(self::$instance instanceof self)) { 
 self::$instance = new self(); 
 } 
 return self::$instance; 
 } 
} 
$a =Database::getInstance(); 
$b =Database::getInstance(); 
// true 
var_dump($a === $b); 
 

2.工厂设计模式

要是当操作类的参数变化时,只用改相应的工厂类就可以

例子

<?php 
interface InterfaceShape 
{ 
 function getArea(); 
 function getCircumference(); 
} 
/** 
* 矩形 
*/ 
class  rect angle implements InterfaceShape 
{ 
 private $width; 
 private $height; 
 public function __construct($width, $height) 
 { 
 $this->width = $width; 
 $this->height = $height; 
 } 
 public function getArea() 
 { 
 return $this->width* $this->height; 
 } 
 public function getCircumference() 
 { 
 return 2 * $this->width + 2 * $this->height; 
 } 
} 
/** 
* 圆形 
*/ 
class Circle implements InterfaceShape 
{ 
 private $radius; 
 function __construct($radius) 
 { 
 $this->radius = $radius; 
 } 
 public function getArea() 
 { 
 return M_PI * pow($this->radius, 2); 
 } 
 public function getCircumference() 
 { 
 return 2 * M_PI * $this->radius; 
 } 
} 
/** 
* 形状工厂类 
*/ 
class FactoryShape 
{ 
 public static function create() 
 { 
 switch (func_num_args()) { 
 case1: 
 return newCircle(func_get_arg(0)); 
 case2: 
 return newRectangle(func_get_arg(0), func_get_arg(1)); 
 default: 
 # code... 
 break; 
 } 
 } 
} 
$rect =FactoryShape::create(5, 5); 
// object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) } 
var_dump($rect); 
echo "<br>"; 
// object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) } 
$circle =FactoryShape::create(4); 
var_dump($circle); 
 

3.观察者设计模式

观察者模式 是挺常见的一种设计模式,使用得当会给程序带来非常大的便利,使用得不当,会给后来人一种难以维护的想法。

使用场景: 用户登录,需要写日志,送积分,参与活动 等使用消息队列,把用户和日志,积分,活动之间解耦合

什么是观察者模式? 一个对象通过提供方法允许另一个对象即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!

<?php 
/* 
观察者接口 
*/ 
interface Interface observer  
{ 
 function onListen($sender, $args); 
 function getObserverName(); 
} 
// 可被观察者接口 
interface InterfaceObservable 
{ 
 function addObserver($observer); 
 function removeObserver($observer_name); 
} 
// 观察者抽象类 
abstract class Observer implements InterfaceObserver 
{ 
  protected  $observer_name; 
 function getObserverName() 
 { 
 return $this->observer_name; 
 } 
 function onListen($sender, $args) 
 { 
 } 
} 
// 可被观察类 
abstract class Observable implements InterfaceObservable 
{ 
 protected $observers = array(); 
 public function addObserver($observer) 
 { 
 if ($observerinstanceofInterfaceObserver) 
 { 
 $this->observers[] = $observer; 
 } 
 } 
 public function removeObserver($observer_name) 
 { 
  foreach  ($this->observersas $index => $observer) 
 { 
 if ($observer->getObserverName() === $observer_name) 
 { 
 array_splice($this->observers, $index, 1); 
 return; 
 } 
 } 
 } 
} 
// 模拟一个可以被观察的类 
class A extends Observable 
{ 
 public function addListener($listener) 
 { 
 foreach ($this->observersas $observer) 
 { 
 $observer->onListen($this, $listener); 
 } 
 } 
} 
// 模拟一个观察者类 
class B extends Observer 
{ 
 protected $observer_name = 'B'; 
 public function onListen($sender, $args) 
 { 
 var_dump($sender); 
 echo "<br>"; 
 var_dump($args); 
 echo "<br>"; 
 } 
} 
// 模拟另外一个观察者类 
class C extends Observer 
{ 
 protected $observer_name = 'C'; 
 public function onListen($sender, $args) 
 { 
 var_dump($sender); 
 echo "<br>"; 
 var_dump($args); 
 echo "<br>"; 
 } 
} 
$a = new A(); 
// 注入观察者 
$a->addObserver(new B()); 
$a->addObserver(new C()); 
// 可以看到观察到的信息 
$a->addListener('D'); 
// 移除观察者 
$a->removeObserver('B'); 
// 打印的信息: 
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } 
// string(1) "D" 
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } 
// string(1) "D" 
 

4.适配器模式

将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作。

应用场景 :老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。

例如:php连接数据库的方法:mysql,,mysqli,pdo,可以用适配器统一

//老的代码 
class User { 
 private $name; 
 function __construct($name) { 
 $this->name = $name; 
 } 
 public function getName() { 
 return $this->name; 
 } 
} 
//新代码,开放平台标准接口 
interface UserInterface { 
 function getUserName(); 
} 
class UserInfo implements UserInterface { 
 protected $user; 
 function __construct($user) { 
 $this->user = $user; 
 } 
 public function getUserName() { 
 return $this->user->getName(); 
 } 
} 
$olduser = new User('张三'); 
echo $olduser->getName()."n"; 
$newuser = new UserInfo($olduser); 
echo $newuser->getUserName()."n"; 
 

5.策略模式

将一组特定的行为和算法封装成类,以适应某些特定的上下文环境。

使用场景: 个人理解,策略模式是依赖注入,控制反转的基础

例如:一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有广告位展示不同的广告

MaleUserStrategy.php

<?php 
namespace IMooc; 
class MaleUserStrategy implements UserStrategy { 
 function showAd() 
 { 
 echo "IPhone6"; 
 } 
 function showCategory() 
 { 
 echo "电子产品"; 
 } 
} 
 

FemaleUserStrategy.php

<?php 
namespace IMooc; 
class FemaleUserStrategy implements UserStrategy { 
 function showAd() 
 { 
 echo "2014新款女装"; 
 } 
 function showCategory() 
 { 
 echo "女装"; 
 } 
} 
 

UserStrategy.php

<?php 
namespace IMooc; 
interface UserStrategy { 
 function showAd(); 
 function showCategory(); 
} 
 
<?php 
interface FlyBehavior{ 
 public function fly(); 
} 
class FlyWithWings implements FlyBehavior{ 
 public function fly(){ 
 echo "Fly With Wings \n"; 
 } 
} 
class FlyWithNo implements FlyBehavior{ 
 public function fly(){ 
 echo "Fly With No Wings \n"; 
 } 
} 
class Duck{ 
 private $_flyBehavior; 
 public function performFly(){ 
 $this->_flyBehavior->fly(); 
 } 
 public function setFlyBehavior(FlyBehavior $behavior){ 
 $this->_flyBehavior = $behavior; 
 } 
} 
class RubberDuck extends Duck{ 
} 
// Test Case 
$duck = new RubberDuck(); 
/* 想让鸭子用翅膀飞行 */ 
$duck->setFlyBehavior(new FlyWithWings()); 
$duck->performFly(); 
/* 想让鸭子不用翅膀飞行 */ 
$duck->setFlyBehavior(new FlyWithNo()); 
$duck->performFly(); 
 

6.装饰器模式

使用场景: 当某一功能或方法draw,要满足不同的功能需求时,可以使用装饰器模式;实现方式:在方法的类中建addDecorator(添加装饰器),beforeDraw,afterDraw 3个新方法, 后2个分别放置在要修改的方法draw首尾.然后创建不同的装器类(其中要包含相同的,beforeDraw,afterDraw方法)能过addDecorator添加进去,然后在beforeDraw,afterDraw中循环处理,与观察者模式使用有点相似

1.装饰器模式(Decorator),可以动态地添加修改类的功能

2.一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法

3.使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性

DrawDecorator.php

<?php 
namespace IMooc; 
interface DrawDecorator 
{ 
 function beforeDraw(); 
 function afterDraw(); 
} 
 

Canvas.php

<?php 
namespace IMooc; 
class Canvas 
{ 
 public $data; 
 protected $decorators = array(); 
 //Decorator 
 function init($width = 20, $height = 10) 
 { 
 $data = array(); 
 for($i = 0; $i < $height; $i++) 
 { 
 for($j = 0; $j < $width; $j++) 
 { 
 $data[$i][$j] = '*'; 
 } 
 } 
 $this->data = $data; 
 } 
 function addDecorator(DrawDecorator $decorator) 
 { 
 $this->decorators[] = $decorator; 
 } 
 function beforeDraw() 
 { 
 foreach($this->decorators as $decorator) 
 { 
 $decorator->beforeDraw(); 
 } 
 } 
 function afterDraw() 
 { 
 $decorators = array_reverse($this->decorators); 
 foreach($decorators as $decorator) 
 { 
 $decorator->afterDraw(); 
 } 
 } 
 function draw() 
 { 
 $this->beforeDraw(); 
 foreach($this->data as $line) 
 { 
 foreach($line as $ char ) 
 { 
 echo $char; 
 } 
 echo "<br />\n"; 
 } 
 $this->afterDraw(); 
 } 
 function rect($a1, $a2, $b1, $b2) 
 { 
 foreach($this->data as $k1 => $line) 
 { 
 if ($k1 < $a1 or $k1 > $a2) continue; 
 foreach($line as $k2 => $char) 
 { 
 if ($k2 < $b1 or $k2 > $b2) continue; 
 $this->data[$k1][$k2] = ' '; 
 } 
 } 
 } 
} 
 

ColorDrawDecorator.php

<?php 
namespace IMooc; 
class ColorDrawDecorator implements DrawDecorator 
{ 
 protected $color; 
 function __construct($color = 'red') 
 { 
 $this->color = $color; 
 } 
 function beforeDraw() 
 { 
 echo "<div style='color: {$this->color};'>"; 
 } 
 function afterDraw() 
 { 
 echo "</div>"; 
 } 
} 
 

index.php

<?php 
define('BASEDIR', __DIR__); 
include BASEDIR.'/IMooc/Loader.php'; 
spl_autoload_register('\\IMooc\\Loader::autoload'); 
$canvas = new IMooc\Canvas(); 
$canvas->init(); 
$canvas->addDecorator(new \IMooc\ColorDrawDecorator('green')); 
$canvas->rect(3,6,4,12); 
$canvas->draw();
 

文章来源:智云一二三科技

文章标题:PHP常见的设计模式

文章地址:https://www.zhihuclub.com/78390.shtml

关于作者: 智云科技

热门文章

网站地图