【问题标题】:I need an explanation of a wrapper class with an example that a child would understand我需要一个孩子能理解的例子来解释一个包装类
【发布时间】:2012-03-11 09:20:20
【问题描述】:

我读过this entire post。它向其他有经验的程序员描述了包装类是什么,但对像我这样的新手却没有。

我了解 PHP 语法,即面向对象的概念,但还没有用面向对象的代码编写我自己的应用程序。当我试图弄清楚包装类到底是什么时,我感到非常困惑。我不懂技术术语。

我希望有人用一个漂亮的详细的孩子般的描述来回答,对于那些了解面向对象程序的基础并且阅读了几乎整个 php.net 语言参考但没有实际面向对象的人来说,这很容易理解编程经验。尚未编写任何应用程序。

【问题讨论】:

    标签: php


    【解决方案1】:

    由于您链接到的问题的解释非常广泛,我不会再为您重新定义它。相反,我将尝试通过注入示例向您展示。

    class Logger {
    
        private $__logger;
    
        public function __construct($logger) {
            $class = $logger . "Logger";
            $this->$__logger = new $class();
        }
    
        public function write($message) {
            $this->$__logger->write($message);
        }
    }
    

    所以,在上面你有一个类Logger,你可能会用它在某处记录信息。我们并不真正关心它是如何做到的,我们只知道它会做到。

    现在,我们有几种不同的日志记录可能性...

    class DBLogger {
    
        public function write($message) {
            // Connect to the database and 
            // INSERT $message
        }
    }
    
    class FileLogger {
    
        public function write($message) {
            // open a file and
            // fwrite $message
        }
    }
    
    class EMailLogger {
    
        public function write($message) {
            // open an smtp connection and 
            // send $message
        }
     }
    

    现在,当我们使用我们的记录器时,我们可以通过以下任一方式来实现:

    $logger = new Logger("DB");
    $logger = new Logger("EMail");
    $logger = new Logger("File");
    

    我们总是以相同的方式与$logger 交互(即我们调用write($message))。包装器实例Logger 包装了实际的日志记录类并代表我们调用它的方法。

    上述代码类型的更常见用途是使用配置文件来确定您的记录器是什么。例如,考虑您希望将日志记录发送到文件的情况。您可能有一个如下所示的配置:

    $logging = array( 
                   'type' => 'file',
                   'types' => array(
                       'file' => array(
                           'path' => '/var/log'
                           'name' => 'app_errors.log'
                        ),
                        'email' => array(
                           'to' => 'webmaster@domain.com',
                           'from' => 'error_logger@domain.com',
                           'subject' => 'Major fail sauce'
                        ),
                        'db' => array(
                            'table' => 'errors',
                            'field' => 'error_message'
                        )
                    )
    );
    

    您的改编课程可能如下所示:

    class FileLogger {
    
        public function __construct() {
            // we assume the following line returns the config above.  
            $this->config = Config::get_config("logger");
        }
    
        public function write($message) {
            $fh = fopen($this->config->path . '/' . $this->config->file);
            fwrite($fh, $message . "\n");
            fclose($fh);
        }
    }
    

    我们会为其他 adapted 类做同样的事情。然后,对主 Wrapper Logger 稍作修改,我们可以使用配置数据创建正确的封装实例,并将其基于配置中定义的 type。一旦你有了类似的东西,切换到通过电子邮件进行日志记录就像在配置中更改 type 一样简单。

    【讨论】:

    • 非常感谢!现在我正式理解了这个概念。虽然,不要误会我的意思。我能看到的例子越多,我的理解就会越好。感谢您花时间写出这个例子。非常感谢,我希望其他人能找到您的回复!
    • @sberry 包装类可以使用继承吗?
    【解决方案2】:

    包装类只是让他们的子类更容易在特定情况下使用。编写了许多库以涵盖各种情况,因此使用起来变得麻烦且复杂。很多项目都会为库创建一个包装器以使其更易于使用。

    以这个 PDO 类的用法为例:

    $sth = $dbh->prepare('SELECT name, colour, calories
        FROM fruit
        WHERE calories < :calories AND colour = :colour');
    $sth->bindParam(':calories', $calories, PDO::PARAM_INT);
    $sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
    $sth->execute();
    

    不要太担心细节。只知道这些代码行查询数据库。包装类允许与上述相同的功能,例如:

    Db::query('SELECT name, colour, calories
      FROM fruit
      WHERE calories < :calories AND colour = :colour',
      array($calories, $colour));
    

    我们已将子类的一些繁琐但很少使用的功能移除到易于使用的界面中。在内部,包装类正在构建对 PDO 的相同类型的调用,但开发人员隐藏

    免责声明:这些例子只是......例子。不是为了展示最佳实践,甚至是实用的。

    【讨论】:

    • IE 有时,原始代码作者甚至从未想过“易用性”,所以有时需要其他人来制作一个包装类来实现这一点。编辑更公平:有时原始代码作者没有意识到他们的代码将用于其他平台或用途。
    • 迈克!对您的回应与对 sberry 的回应相同!非常感谢!我现在可以稍微了解它的用途。我希望有某种方法可以将此帖子链接到原始帖子中的链接,以便其他人也可以从中受益!
    猜你喜欢
    • 2019-02-21
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2011-06-09
    • 2023-03-26
    • 2022-07-06
    相关资源
    最近更新 更多