【问题标题】:how interfaces are used for loose coupling?接口如何用于松散耦合?
【发布时间】:2013-07-29 13:08:33
【问题描述】:

我似乎没有掌握接口如何实现松散耦合的概念?您可能会发现这个问题与其他一些问题重复,但我已经阅读了许多与该主题相关的答案,但我还没有找到令人满意的解释。

以下是有多少开发人员实施松散耦合的示例。

interface shape {
   public function sayName();
}

class Circle implements shape {

     public function sayName(){
          echo 'Hello my name is circle';
      }
}

class Square implements shape {

     public function sayName(){
          echo 'Hello my name is square';
      }
}

class Creator {
       public $shape = null;
       public function __construct(Shape $shape){
          $this->shape = $shape;
       }
}

$circle = new Creator(new Circle());
$circle->sayName();

$square = new Creator(new Square());
$square->sayName();

在上面的例子中,我们使用了接口的多态性来实现松耦合。但我没有看到这段代码是松散耦合的。在上面的示例中,调用代码(客户端)使用“new”运算符直接引用“Circle”和“Square”类,因此创建了紧密耦合。

为了解决这个问题,我们可以这样做。

界面形状{ 公共函数sayName(); }

class Circle implements shape {

     public function sayName(){
          echo 'Hello my name is circle';
      }
}

class Square implements shape {

     public function sayName(){
          echo 'Hello my name is square';
      }
}

class Creator {
       public $shape = null;
       public function __construct($type){
          if(strtolower($type) == 'circle'){
             $this->shape = new Circle();
          } else if(strtolower($type) == 'square'){
             $this->shape = new Square();
          } else {
             throw new Exception('Sorry we don\'t have '.$type.' shape');
          }
       }
}

$circle = new Creator('Circle');
$circle->sayName();

$square = new Creator('Square');
$square->sayName();

这个例子修复了前面例子的问题,但我们根本不使用接口。

我的问题是,如果我可以在没有接口的情况下实现松散耦合,为什么还要使用接口?在上述情况下,接口会提供什么好处?或者如果我在上面的例子中不使用接口会遇到什么问题?

感谢您的帮助。

【问题讨论】:

  • 而且通过你的方法,每次你想要一个像三角形、梯形或五边形这样的新形状时,你都必须重写 Creator 的 constructor() 方法代码......松耦合意味着 不必重写 Creator 代码,只需创建一个实现 Shape 的新类
  • @MarkBaker 你错了。我将拥有一个创作者,我可以拥有成千上万的客户。重写一个创作者或一千个客户哪个更好?
  • @JayBhatt 这毫无意义。
  • 接口与您在 Creator 类中尝试完成的任务没有任何关系。您正在尝试开发一个系统来将字符串值映射到类实现。与接口唯一相关的是生成的类应该实现接口。
  • 这是一种简化的服务定位策略,但恕我直言,我认为它的可扩展性不足以处理 1000 种类型而不会造成维护的噩梦。其他实现使用某种配置文件将字符串映射到类实现。关键是Creator出来的东西应该实现需要的接口。

标签: php oop design-patterns architecture


【解决方案1】:

正如其他人所指出的,您正在做的更多是依赖注入,这是一个相关但独立于松散耦合的主题。我将尝试深入了解通过接口实现松散耦合的简单应用。

我倾向于将接口视为定义/执行合同的便捷方式。考虑一个需要将每个形状渲染为图像的情况,而不是每个形状都可以打招呼的简单示例。

这个伪代码展示了如何在没有界面的情况下处理 Squares 和 Circles。

class Circle {
  function renderCircle() { ... }
}

class Square {
  function renderSquare() { ... }
}

// then when we use them
Circle[] circlesArray = loadCircles
Square[] squaresArray = loadSquares

foreach(circle in circlesArray){
  circle.renderCircle
}

foreach(square in squaresArray){
  square.renderSquare
}

如果相反,我们说我们不太关心它的形状是什么type,而只关心你可以渲染它,我们最终会得到以下界面:

interface renderableShape {
  function render()
}

在您只关心渲染形状的能力的情况下,您针对该界面进行编程。

你可以有这样的东西:

function renderShapes(Array[renderableShape] shapes){
  foreach(shape in shapes){
    shape.render()
  }
}

您现在确保您的 renderShapes 函数无法查看 Circle 或 Square 实现的任何具体细节。它只需要知道您可以致电render

【讨论】:

    猜你喜欢
    • 2012-02-18
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2011-02-22
    • 2014-03-15
    • 2010-11-28
    • 2014-05-29
    相关资源
    最近更新 更多