使用 TypeScript 解释 D is SOLID 原则

Explanation of the D is SOLID principles using TypeScript

我最近在看一篇关于 SOLID 原则的文章,我似乎无法理解有关依赖倒置原则 (DIP) 的示例。文章举了下面的例子。首先是错误的方式,然后是正确的方式。

方法不正确

class Login { 
  login(googleLogin: any) { 
    // some code which will be used for google login.
  }
}

有道理,文章解释说,如果客户明天想添加 Facebook 登录名,您将不得不修改登录名 class,这在 DIP 中应该没有必要。依赖于抽象而不是具体化。明白了。

正确的方法

interface ISocialLogin {
  login(options: any);
}

class GoogleLogin implements ISocialLogin { 
  login(googleLogin: any) { 
    // some code which will be used for google login.
  }
}

class FBLogin implements ISocialLogin { 
  login(fbLogin: any) { 
    // some code which will be used for fb login.
  }
}

class Login {
  constructor(private login: ISocialLogin) {}

  onLogin() {
    this.login();
  }
}

现在,在这个例子中..我们如何知道登录 class 将使用哪个 class?我可以看到您是否在构造函数中指定了 GoogleLogin 与 FBLogin,但只是实现接口让我感到困惑。有人可以解释一下吗?提前致谢。

正在编辑其他问题...

我认为我仍然缺少一些基本的东西。在此示例中(Angular 具体),假设我有以下 UX。在 LoginComponent 内部,我有一个 GoogleLoginComponent 和一个 FacebookLoginComponent。在这两个子组件示例中,我将使用 GoogleLogin 和 FBLogin classes,对吗?

TL;DR: zerkms 在评论中给了你正确的答案。

长答案: 此问题的依赖倒置原则的要点是您的登录实现独立于 ISocialLogin 的实际实现。您只能使用 ISocialLogin 提供的属性和方法,但只要作为您的 Login 构造函数的参数收到的 class 实现了它们,您的组件将独立于底层登录实现。

这里的诀窍是,现在 select 用于登录实施的实例不需要登录,因为它是从外部提供的。这将使您可以在任何地方使用 Login+ISocialLogin 组件。例如,一个新的应用程序可能会提供不同的社交登录实现,您将能够重用该组件。在前者(即不正确的方式)中,构造函数和 Login 中使用它的任何其他方法都需要重做,因为它取决于 GoogleLogin 实现。

总而言之,您已经摆脱了这种依赖(由括号分隔的独立组件;箭头方向表示 "depends on"):

(Login) -> (GoogleLogin)

至:

(Login -> ISocialPlugin) <- (GoogleLogin)