0

假设您正在编写一个“更大”的应用程序,并且您想在类中记录某些错误。现在几乎每个班级都需要访问 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 并不是真正的Position类的一部分,例如$xand $y。它只是一个实用程序。

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

4

2 回答 2

1

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

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

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

这个链接上,您可以查看如何使用postsharp实现日志记录,这是一个 C# AOP 框架

于 2013-03-01T12:29:26.850 回答
1

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

我在这里看到两个选项:

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

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

不幸的是,我并不精通 PHP,所以我无法为您提供代码示例。但我确实在 C# 中找到了这个 AOP 的好例子:http: //visualstudiomagazine.com/articles/2011/05/12/wccsp_aspect-orientation-programming.aspx

于 2013-03-01T13:10:51.273 回答