PHP八大设计模式|代码示例

2019年8月29日 0 条评论 12.04k 次阅读 0 人点赞

一、单例模式

单例模式指的就是使某个类的对象仅允许被创建一次

应用场景: 一般创建一个对象需要消耗过多的资源,如:访问I0和数据库等资源或者有很多个地方都用到了这个实例。

具体代码实例:

这里我们需要注意几点:

  • 构造函数和析构函数必须声明为私有,防止外部程序new 类从而失去单例模式的意义
  • getInstance()方法必须设置为公有的,必须调用此方法 以返回实例的一个引用
  • ::操作符只能访问静态变量和静态函数
  • 使用单例模式生成一个对象后, 该对象可以被其它众多对象所使用

二:工厂模式

工厂模式是使用工厂类中的方法来生成某个对象的,而不是在代码中直接new该对象。使用工厂模式,可以避免当改变某个类的名字或者方法之后,在调用这个类的所有的代码中都修改它的名字或者参数。

模拟场景:我的一个项目中100个文件都使用到了第三方类库Test.php这个文件,因此在100个文件中我都需要new Test();但是某一天我将这个类的名字重命名后,改为Test1,那么我需要进入100个文件中把new Test();都改成new Test1();吗?
显然这样很不合理

解决方案代码示例说明

我拥有三个文件:(文件1:入口文件index.php)(文件2:工厂类文件:Factory.php)(文件3:第三方类库文件:Test.php)

以下是index.php代码示例:

以下是Factory.php代码示例

以下是Test.php代码示例:

此时,访问index.php这个文件时,我们就能调用Test.php这个类文件。

某一天我需要改变Test这个类的类名,只需要更改Test.php的文件名、Test类名以及Factory工厂类中new Test();中的这个Test名字即可。100个文件要使用Test这个类,仅仅只需要将工厂类引入,并且调用即可。但是前提是要注册监听自动载入函数autoload();

三、注册模式

注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。

示例代码:

四:适配器模式

具体作用:将各种截然不同的函数接口封装成统一的API。

举例说明:PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。

具体实现方法如下:

首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。

代码示例:

MySQL的API定制

Mysqli定制API

PDO定制

总结:通过以上案例,PHP与MySQL的数据库交互有三套API,在不同的场景下可能使用不同的API,那么开发好的代码,换一个环境,可能就要改变它的数据库API,那么就要改写所有的代码,使用适配器模式之后,就可以使用统一的API去屏蔽底层的API差异带来的环境改变之后需要改写代码的问题。

五、策略模式

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

举例说明:假如有一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有的广告位展示不同的广告。在传统的代码中,都是在系统中加入各种if else的判断,硬编码的方式。如果有一天增加了一种用户,就需要改写代码。使用策略模式,如果新增加一种用户类型,只需要增加一种策略就可以。其他所有的地方只需要使用不同的策略就可以。

代码实现:

首先声明策略的接口文件,约定了策略的包含的行为。然后,定义各个具体的策略实现类

以下文件为:UserStrategy.php

以下文件为 :FemaleUser.php

以下文件为 : MaleUser.php

以下文件为 :Page.php(策略分析文件)

总结:通过以上方式,可以发现,在不同用户登录时显示不同的内容,并且解决了在显示时的硬编码的问题。如果要增加一种策略,只需要增加一种策略实现类,然后在入口文件中执行判断,传入这个类即可。实现了解耦。

六、观察者模式

用模式开发的优点是,能让我们的逻辑结构以及代码更加清晰,便于维护!

而我们为什么要用 “观察者模式”?这就需要从实际运用中来理解才能更好的运用!用如下的情境来说明吧。

事例:开始时我被安排做项目的登录,很快我就完成了。然后产品提出了另一个需求,用户登录后,给他们推送一条实时消息!然后我在登录成功的逻辑后加了一段代码,完成了登录后的实时消息推送。然而事情还没有完,产品又给加了个需求,需要给新登录的用户10块钱红包奖励,这个当然很简单,我又在消息推送后加了代码,完成了新登录用户的红包奖励(钱怎么到账的过程暂且不论),然而事情还没完没了了,产品不断的在加需求了,如非vip用户登录,给他推送10条需要注册VIP才能打开的信息,如根据客户习惯推送10条客户偏好的信息,如vip快到期的客户需要在客户登录后提醒要充值啦。。。。。。。等等,如是这般,那我就得不停的在登录后加代码,变得我开始看不懂哪个xxx写的代码了!

那么此时我们就得考虑用"观察者模式" 了

可以以这样的方式简单明了形容 观察者模式, 某个商场门口安排一个人进行观察,观察到有a类型的顾客进门,立即安排敲锣、打鼓、送鲜花,观察到有b类客户,立即安排购物袋,观察到c类客户,嗯嗯感觉他是来打酱油了,安排不要浪费表情了,什么欢迎仪式也没有。。。。。也就是说 观察者就是个‘势利眼’,看人下彩,根据观察给进来的顾客安排对应的某个服务或者某些服务!也许这个形容还不够恰当,但大体意思差不多了。

接下来就是重点了,描述了观察者模式的轮廓,那么就需要转化为代码来实际运用了!

一、首先得有两个接口类,用以框定观察者模式,一个被观察者接口类(一般申明有三个必须方法)

  • 添加观察者对象的方法
  • 删除观察者对象的方法
  • 通知观察者进行相应执行方法

一个观察者接口类(一般只有一个必须方法,就是执行)

如果直接甩代码可能有点难理解,那么就先给个示意图来明确一下吧!

二、根据观察者接口类的框定我们定下接口类如下代码:

三、根据框定的结构,大概的理解一下就是,要实现 被观察者对象 存储各种观察者对象(完成各种功能的对象)存储起来,然后通只各观察者执行自己的功能,先看看如下的实现代码

七、原型模式

1.有些时候,我们需要创建多个类似的大对象。如果直接通过new对象,开销很大,而且new完还得进行重复的初始化工作。可能把初始化工作封装起来的,但是对于系统来说,你封不封装,初始化工作还是要执行。

2.原型模式则不同,原型模式是先创建好一个原型对象,然后通过clone这个原型对象来创建新的对象,这样就免去了重复的初始化工作,系统仅需内存拷贝即可。

举例说明:如果说,我们现在正开发一个游戏,有不同的地图,地图大小都是一样的,并且都有海洋,但是不同的地图温度不一样。

八、装饰模式

为什么需要装饰器模式:

  • 我们要对一个已有的对象添加新功能,又不想修改它原来的结构。
  • 使用子类继承的方法去实现添加新功能,会不可避免地出现子类过多,继承链很长的情况。而且不少书籍都规劝我们竭力保持一个对象的父与子关系不超过3个。
  • 装饰器模式,可以提供对对象内容快速非侵入式地修改。

举例说明: 如果有一个游戏角色,他原来是默认没穿衣服的。现在游戏改进了,觉得这个角色,你可以自行搭配穿搭风格~

代码示例如下:

兰陵美酒郁金香

大道至简 Simplicity is the ultimate form of sophistication.

文章评论(0)

你必须 登录 才能发表评论