• 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	est();//通过这种方式,使用命名空间下的方法或者类。Test1表示命名空间,test()表示该命名空间下的一个方法。
    echo "<br>";
    Test2	est();
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果
    这里写图片描述
    总结:通过以上代码,可以看到,在不同的命名空间下,可以有相同的类名或者方法名。

    类自动载入

    随着PHP项目的变大,会导致一个PHP文件的前面有很多的require去包含各种依赖的PHP文件。如果某个类删除,但是在别的文件里有导入的情况,就会导致致命错误。解决以上问题的方法,就是__autoload()函数。

    Test1.php
    <?php
    class Test1{
        static function test(){
            echo __FILE__;
        }
    }
    Test2.php
    <?php
    class Test2
    {
        static function test(){
            echo __FILE__;
        }
    }
    Test.php
    <?php
    Test1::test();
    Test2::test();
    
    function __autoload($class){
        $dir  = __DIR__;
        $requireFile = $dir."\".$class.".php";
        require $requireFile;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    PHP就是用这段代码,去动态的载入需要包含的文件。当使用某个类,而这个类没有包含到文件中时,就会调用__autoload()函数,去动态的加载这个文件。但是,当使用多个框架时,每个框架都会有自己的__autoload()实现,所以,会导致文件重复导入。

    <?php
    spl_autoload_register('autoload1');
    spl_autoload_register('autoload2');
    //将实现自动导入的函数,以字符串的形式传入该函数中,即可解决重复导入文件导致的错误问题。
    Test1::test();
    Test2::test();
    
    function autoload1($class){
        $dir  = __DIR__;
        $requireFile = $dir."\".$class.".php";
        require $requireFile;
    }
    function autoload2($class){
        $dir  = __DIR__;
        $requireFile = $dir."\".$class.".php";
        require $requireFile;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    PSR-0

    1. PHP的命名空间必须与绝对路径一致。
    2. 类名首字母大写。
    3. 除了入口文件之外,其他的PHP文件必须是一个类,不能有执行的代码。

    设计模式

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

    单例模式

    1. $_instance必须声明为静态的私有变量
    2. 构造函数和析构函数必须声明为私有,防止外部程序new 类从而失去单例模式的意义
    3. getInstance()方法必须设置为公有的,必须调用此方法 以返回实例的一个引用
    4. ::操作符只能访问静态变量和静态函数
    5. new对象都会消耗内存
    6. 使用场景:最常用的地方是数据库连接。
    7. 使用单例模式生成一个对象后, 该对象可以被其它众多对象所使用。
    8. 私有的__clone()方法防止克隆对象

    单例模式,使某个类的对象仅允许创建一个。构造函数private修饰,
    申明一个static getInstance方法,在该方法里创建该对象的实例。如果该实例已经存在,则不创建。比如只需要创建一个数据库连接。

    工厂模式

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

    Test1.php
    <?php
    class Test1{
        static function test(){
            echo __FILE__;
        }
    }
    
    Factory.php
    <?php
    class Factory{
        /*
         * 如果某个类在很多的文件中都new ClassName(),那么万一这个类的名字
         * 发生变更或者参数发生变化,如果不使用工厂模式,就需要修改每一个PHP
         * 代码,使用了工厂模式之后,只需要修改工厂类或者方法就可以了。
         */
        static function createDatabase(){
            $test = new Test1();
            return $test;
        }
    }
    
    Test.php
    <?php
    spl_autoload_register('autoload1');
    
    $test = Factory::createDatabase();
    $test->test();
    function autoload1($class){
        $dir  = __DIR__;
        $requireFile = $dir."\".$class.".php";
        require $requireFile;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    这里写图片描述

    Test1.php
    <?php
    class Test1{
        protected static  $tt;
        private function __construct(){}
        static function getInstance(){
            if(self::$tt){
                echo "对象已经创建<br>";
                return self::$tt;
            }else {
                self::$tt = new Test1();
                echo "创建对象<br>";
                return self::$tt;
            }
        }
         function echoHello(){
            echo "Hello<br>";
        }
    }
    Test.php
    <?php
    spl_autoload_register('autoload1');
    
    $test = Test1::getInstance();
    $test->echoHello();
    $test = Test1::getInstance();
    $test->echoHello();
    $test = Test1::getInstance();
    $test->echoHello();
    $test = Test1::getInstance();
    $test->echoHello();
    function autoload1($class){
        $dir  = __DIR__;
        $requireFile = $dir."\".$class.".php";
        require $requireFile;
    }

    策略模式

    策略模式,将一组特定的行为和算法封装成类,以适应某些特定的上下文环境。
    eg:假如有一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有的广告位展示不同的广告。在传统的代码中,都是在系统中加入各种if else的判断,硬编码的方式。如果有一天增加了一种用户,就需要改写代码。使用策略模式,如果新增加一种用户类型,只需要增加一种策略就可以。其他所有的地方只需要使用不同的策略就可以。
    首先声明策略的接口文件,约定了策略的包含的行为。然后,定义各个具体的策略实现类。

    UserStrategy.php
    <?php
    /*
     * 声明策略文件的接口,约定策略包含的行为。
     */
    interface UserStrategy
    {
        function showAd();
        function showCategory();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    FemaleUser.php
    <?php
    require_once 'Loader.php';
    class FemaleUser implements UserStrategy
    {
        function showAd(){
            echo "2016冬季女装";
        }
        function showCategory(){
            echo "女装";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    MaleUser.php
    <?php
    require_once 'Loader.php';
    class MaleUser implements UserStrategy
    {
        function showAd(){
            echo "IPhone6s";
        }
        function showCategory(){
            echo "电子产品";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    Page.php//执行文件
    <?php
    require_once 'Loader.php';
    class Page
    {
        protected $strategy;
        function index(){
            echo "AD";
            $this->strategy->showAd();
            echo "<br>";
            echo "Category";
            $this->strategy->showCategory();
            echo "<br>";
        }
        function setStrategy(UserStrategy $strategy){
            $this->strategy=$strategy;
        }
    }
    
    $page = new Page();
    if(isset($_GET['male'])){
        $strategy = new MaleUser();
    }else {
        $strategy = new FemaleUser();
    }
    $page->setStrategy($strategy);
    $page->index();
    

    执行结果图:
    这里写图片描述

    这里写图片描述
    总结:
    通过以上方式,可以发现,在不同用户登录时显示不同的内容,但是解决了在显示时的硬编码的问题。如果要增加一种策略,只需要增加一种策略实现类,然后在入口文件中执行判断,传入这个类即可。实现了解耦。
    实现依赖倒置和控制反转 (有待理解)
    通过接口的方式,使得类和类之间不直接依赖。在使用该类的时候,才动态的传入该接口的一个实现类。如果要替换某个类,只需要提供一个实现了该接口的实现类,通过修改一行代码即可完成替换

  • 相关阅读:
    python常用代码: logging 和 无视locale强制东8区
    近期文摘2
    偶尔用一次windows开发,有点明白为何人觉得macos对开发友好
    zz golang str json map互转
    golang一些有价值文章摘录
    从 'golang新手容易犯的三个错误' 中学到的知识点
    macos下使用postgresql
    python netsnmp与pysnmp
    快速实现python抓包嗅探
    macos下npm install 报错: fsevents .... permission denined
  • 原文地址:https://www.cnblogs.com/isuansuan/p/9755942.html
Copyright © 2020-2023  润新知