2016-10-28 71 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類是你所有的封裝算法將收斂,但不要忘了這一切的「封裝」

策略模式中最重要的是封裝了一系列可在運行時使用的算法!

希望它可以幫助你!