• 售前

  • 售后

热门帖子
入门百科

PHP八大设计模式案例详解

[复制链接]
执着等待等wc 显示全部楼层 发表于 2021-8-14 15:05:13 |阅读模式 打印 上一主题 下一主题
PHP定名空间

可以更好地组织代码,与Java中的包类似。
  1. Test1.php
  2. <?php
  3. namespace Test1;//命名空间Test1
  4. function test(){
  5.     echo __FILE__;
  6. }
  7. Test2.php
  8. <?php
  9. namespace Test2; //命名空间Test2
  10. function test(){
  11.     echo __FILE__;//打印当前文件所在的绝对路径。
  12. }
  13. Test.php
  14. <?php
  15. require 'Test1.php';
  16. require 'Test2.php';
  17. Test1\test();//通过这种方式,使用命名空间下的方法或者类。Test1表示命名空间,test()表示该命名空间下的一个方法。
  18. echo "<br>";
  19. Test2\test();
复制代码
运行结果

总结:通过以上代码,可以看到,在不同的定名空间下,可以有类似的类名大概方法名。
类主动载入

随着PHP项目的变大,会导致一个PHP文件的前面有很多的require去包含各种依靠的PHP文件。假如某个类删除,但是在别的文件里有导入的情况,就会导致致命错误。解决以上题目的方法,就是__autoload()函数。
  1. Test1.php
  2. <?php
  3. class Test1{
  4.     static function test(){
  5.         echo __FILE__;
  6.     }
  7. }
  8. Test2.php
  9. <?php
  10. class Test2
  11. {
  12.     static function test(){
  13.         echo __FILE__;
  14.     }
  15. }
  16. Test.php
  17. <?php
  18. Test1::test();
  19. Test2::test();
  20. function __autoload($class){
  21.     $dir  = __DIR__;
  22.     $requireFile = $dir."\".$class.".php";
  23.     require $requireFile;
  24. }
复制代码
PHP就是用这段代码,去动态的载入需要包含的文件。当使用某个类,而这个类没有包含到文件中时,就会调用__autoload()函数,去动态的加载这个文件。但是,当使用多个框架时,每个框架都会有自己的__autoload()实现,所以,会导致文件重复导入。
  1. <?php
  2. spl_autoload_register('autoload1');
  3. spl_autoload_register('autoload2');
  4. //将实现自动导入的函数,以字符串的形式传入该函数中,即可解决重复导入文件导致的错误问题。
  5. Test1::test();
  6. Test2::test();
  7. function autoload1($class){
  8.     $dir  = __DIR__;
  9.     $requireFile = $dir."\".$class.".php";
  10.     require $requireFile;
  11. }
  12. function autoload2($class){
  13.     $dir  = __DIR__;
  14.     $requireFile = $dir."\".$class.".php";
  15.     require $requireFile;
  16. }
复制代码
PSR-0

       
  • PHP的定名空间必须与绝对路径同等。   
  • 类名首字母大写。   
  • 除了入口文件之外,其他的PHP文件必须是一个类,不能有实验的代码。
设计模式

单例模式解决的是怎样在整个项目中创建唯一对象实例的题目,工厂模式解决的是怎样不通过new创建实例对象的方法。
单例模式

       
  • $_instance必须声明为静态的私有变量   
  • 构造函数和析构函数必须声明为私有,防止外部步伐new 类从而失去单例模式的意义   
  • getInstance()方法必须设置为公有的,必须调用此方法 以返回实例的一个引用   
  • ::操纵符只能访问静态变量和静态函数   
  • new对象都会斲丧内存   
  • 使用场景:最常用的地方是数据库连接。   
  • 使用单例模式天生一个对象后, 该对象可以被其它众多对象所使用。   
  • 私有的__clone()方法防止克隆对象
单例模式,使某个类的对象仅允许创建一个。构造函数private修饰,
申明一个static getInstance方法,在该方法里创建该对象的实例。假如该实例已经存在,则不创建。比如只需要创建一个数据库连接。
工厂模式

工厂模式,工厂方法大概类天生对象,而不是在代码中直接new。
使用工厂模式,可以制止当改变某个类的名字大概方法之后,在调用这个类的所有的代码中都修改它的名字大概参数。
  1. Test1.php
  2. <?php
  3. class Test1{
  4.     static function test(){
  5.         echo __FILE__;
  6.     }
  7. }
  8. Factory.php
  9. <?php
  10. class Factory{
  11.     /*
  12.      * 如果某个类在很多的文件中都new ClassName(),那么万一这个类的名字
  13.      * 发生变更或者参数发生变化,如果不使用工厂模式,就需要修改每一个PHP
  14.      * 代码,使用了工厂模式之后,只需要修改工厂类或者方法就可以了。
  15.      */
  16.     static function createDatabase(){
  17.         $test = new Test1();
  18.         return $test;
  19.     }
  20. }
  21. Test.php
  22. <?php
  23. spl_autoload_register('autoload1');
  24. $test = Factory::createDatabase();
  25. $test->test();
  26. function autoload1($class){
  27.     $dir  = __DIR__;
  28.     $requireFile = $dir."\".$class.".php";
  29.     require $requireFile;
  30. }
复制代码
  1. Test1.php
  2. <?php
  3. class Test1{
  4.     protected static  $tt;
  5.     private function __construct(){}
  6.     static function getInstance(){
  7.         if(self::$tt){
  8.             echo "对象已经创建<br>";
  9.             return self::$tt;
  10.         }else {
  11.             self::$tt = new Test1();
  12.             echo "创建对象<br>";
  13.             return self::$tt;
  14.         }
  15.     }
  16.      function echoHello(){
  17.         echo "Hello<br>";
  18.     }
  19. }
  20. Test.php
  21. <?php
  22. spl_autoload_register('autoload1');
  23. $test = Test1::getInstance();
  24. $test->echoHello();
  25. $test = Test1::getInstance();
  26. $test->echoHello();
  27. $test = Test1::getInstance();
  28. $test->echoHello();
  29. $test = Test1::getInstance();
  30. $test->echoHello();
  31. function autoload1($class){
  32.     $dir  = __DIR__;
  33.     $requireFile = $dir."\".$class.".php";
  34.     require $requireFile;
  35. }
复制代码
注册模式

注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时间,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。
  1. <?php
  2. class Register
  3. {
  4.     protected static  $objects;
  5.     function set($alias,$object)//将对象注册到全局的树上
  6.     {
  7.         self::$objects[$alias]=$object;//将对象放到树上
  8.     }
  9.     static function get($name){
  10.         return self::$objects[$name];//获取某个注册到树上的对象
  11.     }
  12.     function _unset($alias)
  13.     {
  14.         unset(self::$objects[$alias]);//移除某个注册到树上的对象。
  15.     }
  16. }
复制代码
适配器模式

将各种大相径庭的函数接口封装成统一的API。
PHP中的数据库操纵有MySQL,MySQLi,PDO三种,可以用适配器模式统一成同等,使不同的数据库操纵,统一成一样的API。类似的场景另有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成同等。
起首界说一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成同等的方法。
  1. 接口 IDatabase
  2. <?php
  3. namespace IMooc;
  4. interface IDatabase
  5. {
  6.     function connect($host, $user, $passwd, $dbname);
  7.     function query($sql);
  8.     function close();
  9. }
复制代码
  1. MySQL
  2. <?php
  3. namespace IMooc\Database;
  4. use IMooc\IDatabase;
  5. class MySQL implements IDatabase
  6. {
  7.     protected $conn;
  8.     function connect($host, $user, $passwd, $dbname)
  9.     {
  10.         $conn = mysql_connect($host, $user, $passwd);
  11.         mysql_select_db($dbname, $conn);
  12.         $this->conn = $conn;
  13.     }
  14.     function query($sql)
  15.     {
  16.         $res = mysql_query($sql, $this->conn);
  17.         return $res;
  18.     }
  19.     function close()
  20.     {
  21.         mysql_close($this->conn);
  22.     }
  23. }
复制代码
  1. MySQLi
  2. <?php
  3. namespace IMooc\Database;
  4. use IMooc\IDatabase;
  5. class MySQLi implements IDatabase
  6. {
  7.     protected $conn;
  8.     function connect($host, $user, $passwd, $dbname)
  9.     {
  10.         $conn = mysqli_connect($host, $user, $passwd, $dbname);
  11.         $this->conn = $conn;
  12.     }
  13.     function query($sql)
  14.     {
  15.         return mysqli_query($this->conn, $sql);
  16.     }
  17.     function close()
  18.     {
  19.         mysqli_close($this->conn);
  20.     }
  21. }
复制代码
  1. PDO
  2. <?php
  3. namespace IMooc\Database;
  4. use IMooc\IDatabase;
  5. class PDO implements IDatabase
  6. {
  7.     protected $conn;
  8.     function connect($host, $user, $passwd, $dbname)
  9.     {
  10.         $conn = new \PDO("mysql:host=$host;dbname=$dbname", $user, $passwd);
  11.         $this->conn = $conn;
  12.     }
  13. function query($sql)
  14.     {
  15.         return $this->conn->query($sql);
  16.     }
  17.     function close()
  18.     {
  19.         unset($this->conn);
  20.     }
  21. }
复制代码
通过以上案例,PHP与MySQL的数据库交互有三套API,在不同的场景下大概使用不同的API,那么开辟好的代码,换一个情况,大概就要改变它的数据库API,那么就要改写所有的代码,使用适配器模式之后,就可以使用统一的API去屏蔽底层的API差别带来的情况改变之后需要改写代码的题目。
计谋模式

计谋模式,将一组特定的行为和算法封装成类,以顺应某些特定的上下文情况。
eg:假如有一个电商网站体系,针对男性女性用户要各自跳转到不同的商品类目,并且所有的广告位展示不同的广告。在传统的代码中,都是在体系中参加各种if else的判定,硬编码的方式。假如有一天增长了一种用户,就需要改写代码。使用计谋模式,假如新增长一种用户范例,只需要增长一种计谋就可以。其他所有的地方只需要使用不同的计谋就可以。
起首声明计谋的接口文件,约定了计谋的包含的行为。然后,界说各个具体的计谋实现类。
  1. UserStrategy.php
  2. <?php
  3. /*
  4. * 声明策略文件的接口,约定策略包含的行为。
  5. */
  6. interface UserStrategy
  7. {
  8.     function showAd();
  9.     function showCategory();
  10. }
复制代码
  1. FemaleUser.php
  2. <?php
  3. require_once 'Loader.php';
  4. class FemaleUser implements UserStrategy
  5. {
  6.     function showAd(){
  7.         echo "2016冬季女装";
  8.     }
  9.     function showCategory(){
  10.         echo "女装";
  11.     }
  12. }
复制代码
  1. MaleUser.php
  2. <?php
  3. require_once 'Loader.php';
  4. class MaleUser implements UserStrategy
  5. {
  6.     function showAd(){
  7.         echo "IPhone6s";
  8.     }
  9.     function showCategory(){
  10.         echo "电子产品";
  11.     }
  12. }
复制代码
  1. Page.php//执行文件
  2. <?php
  3. require_once 'Loader.php';
  4. class Page
  5. {
  6.     protected $strategy;
  7.     function index(){
  8.         echo "AD";
  9.         $this->strategy->showAd();
  10.         echo "<br>";
  11.         echo "Category";
  12.         $this->strategy->showCategory();
  13.         echo "<br>";
  14.     }
  15.     function setStrategy(UserStrategy $strategy){
  16.         $this->strategy=$strategy;
  17.     }
  18. }
  19. $page = new Page();
  20. if(isset($_GET['male'])){
  21.     $strategy = new MaleUser();
  22. }else {
  23.     $strategy = new FemaleUser();
  24. }
  25. $page->setStrategy($strategy);
  26. $page->index();
复制代码
实验结果图:


总结:
通过以上方式,可以发现,在不同用户登录时体现不同的内容,但是解决了在体现时的硬编码的题目。假如要增长一种计谋,只需要增长一种计谋实现类,然后在入口文件中实验判定,传入这个类即可。实现了解耦。
实现依靠倒置和控制反转 (有待理解)
通过接口的方式,使得类和类之间不直接依靠。在使用该类的时间,才动态的传入该接口的一个实现类。假如要更换某个类,只需要提供一个实现了该接口的实现类,通过修改一行代码即可完成更换。
观察者模式

1:观察者模式(Observer),当一个对象状态发生厘革时,依靠它的对象全部会收到关照,并主动更新。
2:场景:一个变乱发生后,要实验连续串更新操纵。传统的编程方式,就是在变乱的代码之后直接参加处理的逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增长新的逻辑需要修改变乱的主体代码。
3:观察者模式实现了低耦合,非侵入式的关照与更新机制。
界说一个变乱触发抽象类。
  1. EventGenerator.php
  2. <?php
  3. require_once 'Loader.php';
  4. abstract class EventGenerator{
  5.     private $observers = array();
  6.     function addObserver(Observer $observer){
  7.         $this->observers[]=$observer;
  8.     }
  9.     function notify(){
  10.         foreach ($this->observers as $observer){
  11.             $observer->update();
  12.         }
  13.     }
  14. }
复制代码
界说一个观察者接口
  1. Observer.php
  2. <?php
  3. require_once 'Loader.php';
  4. interface Observer{
  5.     function update();//这里就是在事件发生后要执行的逻辑
  6. }
复制代码
  1. <?php
  2. //一个实现了EventGenerator抽象类的类,用于具体定义某个发生的事件
  3. require 'Loader.php';
  4. class Event extends EventGenerator{
  5.     function triger(){
  6.         echo "Event<br>";
  7.     }
  8. }
  9. class Observer1 implements Observer{
  10.     function update(){
  11.         echo "逻辑1<br>";
  12.     }
  13. }
  14. class Observer2 implements Observer{
  15.     function update(){
  16.         echo "逻辑2<br>";
  17.     }
  18. }
  19. $event = new Event();
  20. $event->addObserver(new Observer1());
  21. $event->addObserver(new Observer2());
  22. $event->triger();
  23. $event->notify();
复制代码
当某个变乱发生后,需要实验的逻辑增多时,可以以松耦合的方式去增删逻辑。也就是代码中的赤色部分,只需要界说一个实现了观察者接口的类,实现复杂的逻辑,然后在赤色的部分加上一行代码即可。如许实现了低耦合。
原型模式

原型模式(对象克隆以制止创建对象时的斲丧)
1:与工厂模式类似,都是用来创建对象。
2:与工厂模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。如许就免去了类创建时重复的初始化操纵。
3:原型模式实用于大对象的创建,创建一个大对象需要很大的开销,假如每次new就会斲丧很大,原型模式仅需要内存拷贝即可。
  1. Canvas.php
  2. <?php
  3. require_once 'Loader.php';
  4. class Canvas{
  5. private $data;
  6. function init($width = 20, $height = 10)
  7.     {
  8.         $data = array();
  9.         for($i = 0; $i < $height; $i++)
  10.         {
  11.             for($j = 0; $j < $width; $j++)
  12.             {
  13.                 $data[$i][$j] = '*';
  14.             }
  15.         }
  16.         $this->data = $data;
  17.     }
  18. function rect($x1, $y1, $x2, $y2)
  19.     {
  20.         foreach($this->data as $k1 => $line)
  21.         {
  22.             if ($x1 > $k1 or $x2 < $k1) continue;
  23.            foreach($line as $k2 => $char)
  24.             {
  25.               if ($y1>$k2 or $y2<$k2) continue;
  26.                 $this->data[$k1][$k2] = '#';
  27.             }
  28.         }
  29.     }
  30.     function draw(){
  31.         foreach ($this->data as $line){
  32.             foreach ($line as $char){
  33.                 echo $char;
  34.             }
  35.             echo "<br>;";
  36.         }
  37.     }
  38. }
复制代码
  1. Index.php
  2. <?php
  3. require 'Loader.php';
  4. $c = new Canvas();
  5. $c->init();
  6. / $canvas1 = new Canvas();
  7. // $canvas1->init();
  8. $canvas1 = clone $c;//通过克隆,可以省去init()方法,这个方法循环两百次
  9. //去产生一个数组。当项目中需要产生很多的这样的对象时,就会new很多的对象,那样
  10. //是非常消耗性能的。
  11. $canvas1->rect(2, 2, 8, 8);
  12. $canvas1->draw();
  13. echo "-----------------------------------------<br>";
  14. // $canvas2 = new Canvas();
  15. // $canvas2->init();
  16. $canvas2 = clone $c;
  17. $canvas2->rect(1, 4, 8, 8);
  18. $canvas2->draw();
复制代码
实验结果:

装饰器模式

1:装饰器模式,可以动态的添加修改类的功能
2:一个类提供了一项功能,假如要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重写实现类的方法
3:使用装饰器模式,仅需要在运行时添加一个装饰器对象即可实现,可以实现最大额机动性。
到此这篇关于PHP八大设计模式案例详解的文章就先容到这了,更多相干PHP八大设计模式内容请搜刮草根技能分享以前的文章或继承浏览下面的相干文章盼望大家以后多多支持草根技能分享!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作