【问题标题】:Share important instances without coupling共享重要实例而不耦合
【发布时间】:2013-03-01 12:23:25
【问题描述】:

假设您正在编写一个“更大”的应用程序,并且您想在类中记录某些错误。现在几乎每个班级都需要访问 Logger。

一个简单的解决方案如下(PHP,但这没关系):

class SomeClass {
  public function someMethod() {
    // stuff ...
    Logger::log("something happened");
    // stuff ...
  }
}

这种方法的问题是它使每个使用 Logger 的类都依赖它,并且你不能简单地在没有 Logger 的其他项目中使用相同的类。它是紧密耦合的。而且你不能在不改变SomeClass的实现的情况下改变记录消息的方式。

上述方法的“小”升级如下:

class SomeClass {

  private $logger;

  public function __construct(/* stuff */) {
    $this->logger = LoggerFactory::getLogger();
  }

  public function someMethod() {
    // stuff ...
    $this->logger->log("something happened");
    // stuff ...
  }
}

这并不能真正解决问题,因为 SomeClass 现在只依赖于 LoggerFactory 并且它与它紧密耦合。这样做的好处是,LoggerFactory 现在可以返回 Logger 类的不同实例。因此,如果您想更改记录消息的方式,则无需更改 SomeClass 的实现。

另一种方法是使用依赖注入:

class SomeClass {

  private $logger;

  public function __construct(Logger $logger, /* stuff */) {
    $this->logger = $logger;
  }

  public function someMethod() {
    // stuff ...
    $this->logger->log("something happened");
    // stuff ...
  }
}

现在这不会将SomeClass 耦合到任何特定类。它只需要一个实现Logger 接口的类。但我遇到的问题是,每当您创建对象时,您都需要将 Logger 实例传递给构造函数。

$object = new Position($this->logger, $x, $y);

我遇到的另一个问题是,Logger 并不是像 $x$y 这样的 Position 类的一部分。它只是一个实用程序。

您如何最好地处理这种情况?在这种情况下,耦合和内聚之间的最佳折衷是什么?

【问题讨论】:

    标签: oop coupling cohesion


    【解决方案1】:

    您的方法是正确的,并且回答了控制反转原则。 但是,正如您所说,记录器是应用程序的横切关注点,与 Position 实体无关。换句话说:这纯粹是技术性的,我们不想知道。

    我在这里看到两个选项:

    1) 您通过某种 Manager 类引用所有记录器,并在类级别使用您需要的记录器。此 LoggingManager 必须为解决方案中需要日志记录功能的所有类所知。在使用外部日志框架(例如:Log4Net)时,我经常这样做。

    2) 或者您可以在运行时从提供所需记录器的更高实体(服务)请求记录器。使用依赖注入框架或面向方面编程风格的类配置会从类本身中移除对 Logger 类型(或工厂)的选择。

    很遗憾,我并不精通 PHP,因此无法为您提供代码示例。 但我确实在 C# 中找到了一个很好的 AOP 示例:http://visualstudiomagazine.com/articles/2011/05/12/wccsp_aspect-oriented-programming.aspx

    【讨论】:

    【解决方案2】:

    AOP 是一个很棒的工具,可以让您将日志记录与业务逻辑分开。

    使用 AOP 的最常见场景之一是日志记录,因此可能值得一看。

    您可以分析是否有任何框架适合您的需求,看看效果如何。

    this link 上,您可以了解如何使用 C# AOP 框架 postsharp 实现日志记录

    【讨论】:

    • 听起来不错,但是你有什么例子吗,或者你能给我指出一个开始的位置吗?
    • 我对PHP不是很熟悉,你应该尝试找到一个专门针对它的框架。在 Google 上搜索 AOP php 可能会有所帮助
    • 我一定会这样做的。但请注意:这个问题没有用 PHP 标记,所以如果你可以用你熟悉的语言发布一个例子,只是为了得到一个基本的想法,那就太棒了。这也将提高这个问题/答案对未来读者的价值。
    • 添加了一个 C# 上著名的 AOP 框架的链接,如果有帮助请告诉我
    猜你喜欢
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2019-07-31
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多