论WordPress的单例模式,和更好的初始化方法

WordPress中,插件使用单例模式,性能更好,免得资源浪费。

平时,以面向对象的写法是这样的:

class Plugin
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        // Actions
        add_action('wp_enqueue_scripts', array($this, 'enqueue_script'));

        // Filters
        add_filter('the_content', array($this, 'the_content'));
    }

    /**
     * 一些方法
     */
    public function enqueue_script()
    {
        // ...
    }
}
$plugin = new Plugin();

或者,其他流行的方法是实例化一个对象类。在外部,使用该实例注册你的动作和过滤器。

class Plugin
{

    public function enqueue_script()
    {
        // ...
    }

    public function the_content($content)
    {
        // ...

        return $content;
    }
}
$plugin = new WP_Kickass_Plugin();

// Actions
add_action('wp_enqueue_scripts', array($plugin, 'enqueue_script'));

// Filters
add_filter('the_content', array($plugin, 'the_content'));

这两种方法都有一个问题,那就是没有一种简单的方法可以在之后将该对象取回,容易被覆盖。当然了,名字可以尽量起得不一样。

实际上,WordPress同样可以使用单例模式,实现单例模式的类有三个元素。你必须:

  1. 有一个私有静态变量来存储实例化的对象。
  2. 将构造函数设为私有。
  3. 创建一个公共静态方法(通常称为“get_instance”)来获取实例化的对象。

看一下前面的两个例子。可以按照上述步骤将它们转换为单例。生成的代码与原始代码非常接近。第一个示例使用构造函数注册所有操作和过滤器,可以在下面看到转换后的代码。

class Plugin
{
   
    private static $instance;

    public static function get_instance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Constructor.
     */
    private function __construct()
    {
        // Actions
        add_action('wp_enqueue_scripts', array($this, 'enqueue_script'));

        // Filters
        add_filter('the_content', array($this, 'the_content'));
    }

    /**
     *加载其他功能
     */
    public function enqueue_script()
    {
        // ...
    }

   
    public function the_content($content)
    {
        // ...

        return $content;
    }
}
$plugin = Plugin::get_instance();

将其转换为单例需要进行一些更改。将构造函数设为私有,并添加了静态变量和“get_instance”方法,结果与前面的示例几乎相同。

同样,可以放到外面来调用:

class Plugin
{

    private static $instance;


    public static function get_instance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Constructor.
     */
    private function __construct()
    {
        // So ronery...
    }


    public function the_content($content)
    {
        // ...

        return $content;
    }
}

// Actions
add_action('wp_enqueue_scripts', array(Plugin::get_instance(), 'enqueue_script'));

// Filters
add_filter('the_content', array(Plugin::get_instance(), 'the_content'));

我们需要创建一个空的私有构造函数。这是因为默认情况下构造函数是公共的。私有构造函数的另一个副作用是我们不能使用new关键字创建对象。我们需要通过调用“get_instance”将其传递给寄存器函数。值得注意的是,单例使第二种方法的吸引力大大降低。如果在构造函数中注册钩子,那么单例模式更有趣。

从构造函数中初始化插件

构造函数的作用是准备对象以供使用,用插件API注册操作和过滤器根本不适合这个任务。使用静态方法创建对象并在那里注册所有内容显然更好。

class Plugin
{
    /**
     * 注册插件
     */
    public static function register()
    {
        $plugin = new self();

        // Actions
        add_action('wp_enqueue_scripts', array($plugin, 'enqueue_script'));

        // Filters
        add_filter('the_content', array($plugin, 'the_content'));
    }

    public function __construct()
    {
        // Setup your plugin object here
    }

    public function enqueue_script()
    {
        // ...
    }
}
Plugin::register();

这使WordPress代码更加解耦。唯一的问题是,一旦对象注册,就不能更改它。
构造函数现在也是公共的,没有必要私有了。这意味着实例化一个新对象对WordPress不再有任何影响。
这些变化还有另一个积极的好处。可以进行类单元可测试。

将插件API拆分为自己的类,这是克服使用单例模式的更高级的方法,其思想是将插件API的使用与所有类分离。创建一个类,该类的唯一责任是与之交互。
这就是我在编写使用接口的示例时想到的,创建该类就不需要在其他类中使用“add_action”和“add_filter”。我们在这里使用插件API,但是对于插件中非常依赖的任何API,都应该这样做。
关于单例模式值得了解,也就是说,使用它是一种选择,你不必这么做。对于你来说,有各种各样的方法来回避单例模式解决的问题。

上一篇 Fancybox 和 lazyload 同时存在的问题
下一篇 WordPress 外链跳转插件 v1.0.0
目录
applek

applek管理员

个人说明在个人中心里面设置

本月创作热力图

最新评论
38658469
38658469
3月31日
guzhang
评论于关于本站
mchsj
mchsj
3月20日
希望增加文章目录
评论于留言建议
吴彦祖
吴彦祖
3月14日
很期待优秀的主题作品qiang
xxx
xxx
3月14日
密码是多少
西风
西风
3月7日
暂时不需要也能跑