使用接口抽象相关功能与使用紧耦合

6 浏览
0 Comments

使用接口抽象相关功能与使用紧耦合

我正在尝试理解紧耦合的真正定义。我已经阅读了关于这个主题的一些帖子,但仍然有一件事让我感到不舒服。\n我理解应该使用接口将类注入到其他类中,而不是具体的实现。我也理解,如果一个类遵循一个接口,那么使用注入接口的任何类都可以调用接口中定义的公共函数并期望相似的功能。\n所以我认为,在只有格式化器改变的情况下,这可以被定义为松耦合的:\n

$example = new OrderGenerator(new CarOrderFormatter);
$example->generate();
$example = new OrderGenerator(new VanOrderFormatter);
$example->generate();

\n然而,我还不太明白的是,当你将责任从彼此分离开来,但这些类仍然紧密地相互关联时。就像这样:\n

$example = new CarOrderGenerator(new CarOrderFormatter);
$example->generate();
$example = new VanOrderGenerator(new VanOrderFormatter);
$example->generate();

\n是的,你可以向这些生成器传递不同的格式化器,但是如果`format`函数期望从`XXXOrderGenerator`具体类中的`generate`函数中得到特定的数据,那么很可能会发生一些错误。\n因此,我认为在上面的最后一个例子中,我已经将责任抽象到了各自的类中,虽然使用了接口,但我不确定这是否仍然是紧耦合的,或者从技术上讲是否是松耦合的?或者我完全误解了问题...

0
0 Comments

问题的出现原因:接口设计不合理,接口的职责不清晰,实现类之间出现了紧耦合的依赖关系。

解决方法:重新设计接口,确保每个接口只负责一个职责或目的。如果接口的实现类违反了单一职责原则或重复了其他接口的职责,说明设计有问题。可以通过以下方式解决:

1. 重新考虑接口的目的和职责,删除或重构不必要的接口。

2. 确保每个接口的实现类都有清晰的目的,不会互相重复或越界。

3. 对于返回值不明确的接口,应该返回固定且明确描述的类型,避免使用模糊的数组类型。可以考虑使用具体的格式对象,每个格式对象实现一个公共访问器来获取订单号和价格等信息。

4. 对于生成订单的接口,可以返回一个订单对象,该订单对象可以包含一个方法来获取适用的格式对象。

通过以上改进,可以清理设计并确保每个实现类的目的更加明确,从而避免出现混乱的依赖关系。

0
0 Comments

紧密耦合的类是指一个类对另一个类具有依赖性,或者依赖于另一个类的内部或特定细节。

在你提供的第一个示例中,OrderGenerator和OrderFormatter并不是紧密耦合的,因为它们都不依赖于对方:它们都依赖于iFormatter。换句话说,OrderFormatter对OrderGenerator一无所知,OrderGenerator对OrderFormatter一无所知,它只知道传递给它的对象实现了'format'函数。当你将CarOrderFormatter或VanOrderFormatter传递给OrderGenerator时,并不会产生负面结果。

在第二个示例中,当将CarOrderFormatter传递给CarOrderGenerator时,你提到如果传递VanOrderFormatter给CarOrderGenerator,则肯定会出现错误。如果CarOrderGenerator代码依赖于CarOrderFormatter的实现细节,那么这些类就是紧密耦合的,即使CarOrderGenerator只看到了iFormatter接口。这段代码会令人困惑,因为CarOrderGenerator在其“契约”中表示它不关心传递的格式化程序是什么,但实际上它确实关心。因此,如果CarOrderGenerator明确表示只能传递CarOrderFormatter给它的构造函数,那么代码的清晰度会更好。然而,引入抽象(即接口的使用)并不是一件坏事,但需要考虑如何定义接口。例如,不仅仅定义一个iFormatter接口,而是定义iCarOrderFormatter和iVanOrderFormatter,它们的定义相同,但CarOrderGenerator要求iCarOrderFormatter,VanOrderGenerator要求iVanOrderFormatter。那么你的示例可能变成:

$example = new CarOrderGenerator(new CarOrderFormatter);
$example->generate();
$example = new CarOrderGenerator(new SportsCarOrderFormatter);
$example->generate();

或者

$example = new VanOrderGenerator(new PassengerVanOrderFormatter);
$example->generate();
$example = new VanOrderGenerator(new CargoVanOrderFormatter);
$example->generate();

关键是要意识到引入接口是为了在不引起问题的情况下灵活地传递给生成器。

0