2016-10-28 73 views
0

我想知道我是否可以得到一些帮助。PHP - 使用接口,策略模式和可选方法参数

我有像这样

interface BackupContract { 
    public function testConn($request, $port); 
} 

接口然后该接口的2个示例实现如下

class FTPBackup implements BackupContract { 
    public function testConn($request, $port = 21) { 
     // code here 
    } 
} 

class SFTPBackup implements BackupContract { 
    public function testConn($request, $port = 22) { 
     // code here 
    } 
} 

正如我所需要的东西等在运行时指定“服务”和端口,即时通讯使用“战略模式”来实现这一点,就像这样。

class BackupStrategy { 
    private $strategy = NULL; 

    public function __construct($service) { 

     switch ($service) { 
      case "ftp": 
       $this->strategy = new FTPBackup(); 
       break; 
      case "sftp": 
       $this->strategy = new SFTPBackup(); 
       break; 
     } 

    } 

    public function testConn($request, $port) 
    { 
     return $this->strategy->testConn($request, $port); 
    } 
} 

最后,在我的控制器im使用下面的代码把它放在一起。

$service = new BackupStrategy($request->input('service')); 
$service->testConn($request, $request->input('port')); 

的问题是,如果用户输入犯规一个端口,它是指自动分配端口变量,即21或22等中的2层的实施方式。

它似乎并不奏效,但它不抛出任何错误

回答

0

您总是在BackupStrategy->testConn($request, $port)方法中设置端口。所以如果有人不给端口,它会传递一个空字符串。

我会实现一个后备功能。

@simon说,你在你的控制器中使用错误的方法名称。

0

要调用testConnection();方法,它不存在。你真正想要调用的是testConn();

检查你的错误报告设置,因为这肯定会引发错误。

+0

对不起,我忘了改变它...它确实检查testConn() – BigJobbies

1

除了Simon和Laurent。

您正在使用接口,所以实现应该匹配。

一个可能的解决方案:

interface BackupContract { 
    public function testConn($request, $port = 0); 
} 

不过,我个人不喜欢这种做法。接口中的可选事物意味着您应该在可能的每个实现中进行验证,而不是相信实现。

其次,我建议使用类型声明(PHP7),例如:

public function foo(int $bar) : bool 
{ 
    return true; 
} 

这个方法只需要一个整数作为参数(必须)和一个布尔值作为返回(必须)。使用$ bar,你确定这个var类型是一个整数。

更多信息请参见:http://php.net/manual/en/migration70.new-features.php

0

但你不应该落实在BackupStrategy的构造的开关。

随着你的不满,你违反了S.O.L.I.D原则中的“开放/关闭”原则。

任何时候您需要添加另一个“备份策略”,您需要修改 BackupStrategy类,将逻辑添加到构造函数中。 那不太好。

您可以制作子版本,每个子版本实施每个备份策略类的实施(LOL),并仅从BackupStrategy类中提供必要的知识。

interface BackupContract { 
    public function testConn($request, $port); 
} 

class FTPBackup implements BackupContract { 
    public function testConn($request, $port = 21) { 
     // code here 
    } 
} 

class SFTPBackup implements BackupContract { 
    public function testConn($request, $port = 22) { 
     // code here 
    } 
} 

class BackupStrategy 
{ 
    private $strategy; 

    public function testConn($request, $port) 
    { 
     return $this->strategy->testConn($request, $port); 
    } 
} 

class ConcreteFTPBackup extends BackupStrategy 
{ 
    function __construct() 
    { 
     $this->strategy = new FTPBackup(); 
    } 
} 

class ConcreteSFTPBackup extends BackupStrategy 
{ 
    function __construct() 
     { 
     $this->strategy = new SFTPBackup(); 
    } 
} 

$service = new ConcreteFTPBackup(); 

$serice->testConn($request, $request->input('port')); 

甚至这样的:

interface BackupContract { 
    public function testConn($request, $port); 
} 

class FTPBackup implements BackupContract { 
    public function testConn($request, $port = 21) { 
     // code here 
    } 
} 

class SFTPBackup implements BackupContract { 
    public function testConn($request, $port = 22) { 
     // code here 
    } 
} 

class BackupStrategy 
{ 
    private $strategy; 

    function __construct(BackupContract $bc) 
    { 
     $this->strategy = $bc(); 
    } 

    public function testConn($request, $port) 
    { 
     return $this->strategy->testConn($request, $port); 
    } 
} 


$service = new BackupStrategy(new FTPBackup()); 

$serice->testConn($request, $request->input('port')); 

然后,你可以实现在运行时的开关。

而且你能在BackupStrategy类setStrategy方法设置或变化运行时的备份策略:

public function setStrategy(BackupContract $bc) 
{ 
    $this->strategy = $bc(); 

} 

所以,现在,你可以在运行时与一个备份策略创建服务,甚至在运行时也改变策略! CHEKIT出来:

$service = new BackupStrategy(new FTPBackup()); 
$service->testConn($request, $request->input('port')); 


$service->setStrategy(new SFTPBackup()); 
$service->testConn($request, $request->input('port')); 

的BackupStrategy类是你所有的封装算法将收敛,但不要忘了这一切的“封装”

策略模式中最重要的是封装了一系列可在运行时使用的算法!

希望它可以帮助你!