我想知道我是否能得到一些帮助。
我有一个像这样的界面
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);
}
}
最后,在我的控制器中使用以下代码将它们放在一起。
$service = new BackupStrategy($request->input('service'));
$service->testConn($request, $request->input('port'));
问题是,如果用户没有输入端口,则意味着自动分配端口变量,即21或22,就像在2个实现中一样。
它似乎不起作用,但它没有抛出任何错误
答案 0 :(得分:4)
但是你不应该在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 out:
$service = new BackupStrategy(new FTPBackup());
$service->testConn($request, $request->input('port'));
$service->setStrategy(new SFTPBackup());
$service->testConn($request, $request->input('port'));
BackupStrategy类是所有封装算法汇聚的地方,但不要忘记所有这些中的“封装”!
策略模式中最重要的是封装了一系列可在运行时使用的算法!
希望它可以帮到你!
答案 1 :(得分:1)
除了Simon和Laurent。
您正在使用接口,因此实施应该匹配。
可能的解决方案:
interface BackupContract {
public function testConn($request, $port = 0);
}
但就个人而言,我不喜欢这种做法。接口中的可选项意味着您应该在每个实现中进行验证,而不是信任实现。
其次,我建议使用类型声明(PHP7),例如:
public function foo(int $bar) : bool
{
return true;
}
此方法需要一个整数作为参数(必须),一个布尔值作为return(必须)。使用$ bar,您确定此var类型是一个整数。
有关详细信息,请参阅:http://php.net/manual/en/migration70.new-features.php
答案 2 :(得分:0)
您正在调用一个不存在的testConnection();
方法。你真正想要的是testConn();
检查错误报告设置,因为这肯定会引发错误。
答案 3 :(得分:0)
您始终使用BackupStrategy->testConn($request, $port)
方法设置端口。因此,如果某人没有给出一个端口,它将传递一个空字符串。
我会实现一个后备功能。
@simon说的是,你在控制器中使用了错误的方法名称。