ASCII码 ASCII码

PHP八大设计模式案例详解

发布于:2022-03-07 10:18:04  栏目:技术文档

这篇文章主要介绍了PHP八大设计模式案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

PHP命名空间

可以更好地组织代码,与Java中的包类似。

Test1.php <?php namespace Test1;//命名空间Test1 function test(){ echo __FILE__; } Test2.php <?php namespace Test2; //命名空间Test2 function test(){ echo __FILE__;//打印当前文件所在的绝对路径。 } Test.php <?php require 'Test1.php'; require 'Test2.php'; Test1\test();//通过这种方式,使用命名空间下的方法或者类。Test1表示命名空间,test()表示该命名空间下的一个方法。 echo "<br>"; 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. <?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. 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:使用装饰器模式,仅需要在运行时添加一个装饰器对象即可实现,可以实现最大额灵活性。

相关推荐
阅读 +