首页 > php教程 > 正文

PHP常用的 五种设计模式及应用场景

转载 2019-03-14 0 7

原标题:PHP常用的 五种设计模式及应用场景

链接:https://blog.csdn.net/NANGE_BOK/article/details/80371526?utm_source=blogxgwz8

爱剁手的你,每天都可以拆红包3次,红包最高1111元,复制以下口令在淘宝打开即可拆红包

€QSMYbhdGJbp€

设计模式六大原则

开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象.

依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。

接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。

迪米特法则:一个对象应该对其他对象保持最少的了解。

1.单例设计模式

所谓单例模式,即在应用程序中最多只有该类的一个实例存在,一旦创建,就会一直存在于内存中!

单例设计模式常应用于数据库类设计,采用单例模式,只连接一次数据库,防止打开多个数据库连接。

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

单例类不能直接实例化创建,而是只能由类本身实例化。因此,要获得这样的限制效果,构造函数必须标记为private,从而防止类被实例化。

需要一个私有静态成员变量来保存类实例和公开一个能访问到实例的公开静态方法。

在PHP中,为了防止他人对单例类实例克隆,通常还为其提供一个空的私有__clone()方法。

使用场景:只实例化一次,内部实例化,对外只有一个开放方法,只能通过调取该方法进行调取实例化对象。数据库连接

单例模式的例子:

<?php

/**

* Singleton of Database

*/

classDatabase

{

// We need a static private variable to store a Database instance.

privatestatic $instance;

// Mark as private to prevent it from being instanced.

privatefunction__construct()

{

// Do nothing.

}

privatefunction__clone()

{

// Do nothing.

}

publicstaticfunctiongetInstance()

{

if(!(self::$instance instanceof self)) {

self::$instance = newself();

}

returnself::$instance;

}

}

$a =Database::getInstance();

$b =Database::getInstance();

// true

var_dump($a === $b);

2.工厂设计模式

工厂模式是另一种非常常用的模式,正如其名字所示:确实是对象实例的生产工厂。某些意义上,工厂模式提供了通用的方法有助于我们去获取对象,而不需要关心其具体的内在的实现

使用场景:使用方法 new实例化类,每次实例化只需调用工厂类中的方法实例化即可。

我们举例子,假设矩形、圆都有同样的一个方法,那么我们用基类提供的API来创建实例时,通过传参数来自动创建对应的类的实例,他们都有获取周长和面积的功能。

<?php

interfaceInterfaceShape

{

functiongetArea();

functiongetCircumference();

}

/**

* 矩形

*/

classRectangleimplementsInterfaceShape

{

private$width;

private$height;

publicfunction__construct($width, $height)

{

$this->width = $width;

$this->height = $height;

}

publicfunctiongetArea()

{

return$this->width* $this->height;

}

publicfunctiongetCircumference()

{

return2* $this->width + 2* $this->height;

}

}

/**

* 圆形

*/

classCircleimplementsInterfaceShape

{

private$radius;

function__construct($radius)

{

$this->radius = $radius;

}

publicfunctiongetArea()

{

returnM_PI * pow($this->radius, 2);

}

publicfunctiongetCircumference()

{

return2* M_PI * $this->radius;

}

}

/**

* 形状工厂类

*/

classFactoryShape

{

publicstaticfunctioncreate()

{

switch(func_num_args()) {

case1:

returnnewCircle(func_get_arg(0));

case2:

returnnewRectangle(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

/*

观察者接口

*/

interfaceInterfaceObserver

{

functiononListen($sender, $args);

functiongetObserverName();

}

// 可被观察者接口

interfaceInterfaceObservable

{

functionaddObserver($observer);

functionremoveObserver($observer_name);

}

// 观察者抽象类

abstractclassObserverimplementsInterfaceObserver

{

protected$observer_name;

functiongetObserverName()

{

return$this->observer_name;

}

functiononListen($sender, $args)

{

}

}

// 可被观察类

abstractclassObservableimplementsInterfaceObservable

{

protected$observers = array();

publicfunctionaddObserver($observer)

{

if($observerinstanceofInterfaceObserver)

{

$this->observers[] = $observer;

}

}

publicfunctionremoveObserver($observer_name)

{

foreach($this->observersas $index => $observer)

{

if($observer->getObserverName() === $observer_name)

{

array_splice($this->observers, $index, 1);

return;

}

}

}

}

// 模拟一个可以被观察的类

classAextendsObservable

{

publicfunctionaddListener($listener)

{

foreach($this->observersas $observer)

{

$observer->onListen($this, $listener);

}

}

}

// 模拟一个观察者类

classBextendsObserver

{

protected$observer_name = 'B';

publicfunctiononListen($sender, $args)

{

var_dump($sender);

echo"<br>";

var_dump($args);

echo"<br>";

}

}

// 模拟另外一个观察者类

classCextendsObserver

{

protected$observer_name = 'C';

publicfunctiononListen($sender, $args)

{

var_dump($sender);

echo"<br>";

var_dump($args);

echo"<br>";

}

}

$a = newA();

// 注入观察者

$a->addObserver(newB());

$a->addObserver(newC());

// 可以看到观察到的信息

$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,可以用适配器统一

//老的代码

classUser{

private$name;

function__construct($name){

$this->name = $name;

}

publicfunctiongetName(){

return$this->name;

}

}

//新代码,开放平台标准接口

interfaceUserInterface{

functiongetUserName();

}

classUserInfoimplementsUserInterface{

protected$user;

function__construct($user){

$this->user = $user;

}

publicfunctiongetUserName(){

return$this->user->getName();

}

}

$olduser = newUser( '张三');

echo$olduser->getName(). "n";

$newuser = newUserInfo($olduser);

echo$newuser->getUserName(). "n";

5.策略模式

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

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

MaleUserStrategy.php

<?php

namespaceIMooc;

classMaleUserStrategyimplementsUserStrategy{

functionshowAd()

{

echo"IPhone6";

}

functionshowCategory()

{

echo"电子产品";

}

}

FemaleUserStrategy.php

<?php

namespaceIMooc;

classFemaleUserStrategyimplementsUserStrategy{

functionshowAd()

{

echo"2017新款女装";

}

functionshowCategory()

{

echo"女装";

}

}

UserStrategy.php

<?php

namespaceIMooc;

interfaceUserStrategy{

functionshowAd();

functionshowCategory();

}

<?php

interfaceFlyBehavior{

publicfunctionfly();

}

classFlyWithWingsimplementsFlyBehavior{

publicfunctionfly(){

echo"Fly With Wings n";

}

}

classFlyWithNoimplementsFlyBehavior{

publicfunctionfly(){

echo"Fly With No Wings n";

}

}

classDuck{

private$_flyBehavior;

publicfunctionperformFly(){

$this->_flyBehavior->fly();

}

publicfunctionsetFlyBehavior(FlyBehavior $behavior){

$this->_flyBehavior = $behavior;

}

}

classRubberDuckextendsDuck{

}

// Test Case

$duck = newRubberDuck();

/* 想让鸭子用翅膀飞行 */

$duck->setFlyBehavior(newFlyWithWings());

$duck->performFly();

/* 想让鸭子不用翅膀飞行 */

$duck->setFlyBehavior(newFlyWithNo());

$duck->performFly();

相关文章


  • 扣丁学堂PHP培训基础之分页原理
  • 为什么说php是web开发最好的语言?
  • 基于ssh/bs/java/asp.net/php/web个人信息门户网
  • 天津PHP培训,老板求我别辞职的原因
  • 《PHP技术大全·第一卷》isset,empty,is_null细致解读
  • 北邮在线PHP学员感言:良师指路 前途无量
  • 培养自己的php编码规范,养成一个好习惯
  • 3篇优秀的PHP开发工程师面试自我介绍范文