PHP-使用接口,策略模式和可选方法参数

Big*_*ies 2 php laravel laravel-5

我想知道我是否能得到一些帮助。

我有一个像这样的界面

interface BackupContract {
    public function testConn($request, $port);
}
Run Code Online (Sandbox Code Playgroud)

然后,此接口的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
    }
}
Run Code Online (Sandbox Code Playgroud)

由于我需要在运行时指定“服务”和端口之类的内容,因此我使用“策略模式”来实现此目的,就像这样。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,在我的控制器中,im使用以下代码将它们放在一起。

$service = new BackupStrategy($request->input('service'));
$service->testConn($request, $request->input('port'));
Run Code Online (Sandbox Code Playgroud)

问题是,如果用户不输入端口,则意味着要自动分配端口变量,即像2个实现中一样分配21或22。

它似乎不起作用,但未引发任何错误

小智 5

但是您不应该在BackupStrategy的构造函数中实现该开关。

通过这种方式,您将违反SOLID原则中的“打开/关闭”原则。

每当您需要添加另一个“备份策略”时,都需要修改 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'));
Run Code Online (Sandbox Code Playgroud)

甚至这个:

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'));
Run Code Online (Sandbox Code Playgroud)

然后,您可以在运行时实现切换。

您也可以在BackupStrategy类中创建setStrategy方法,以在运行时设置或更改备份策略:

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

}
Run Code Online (Sandbox Code Playgroud)

因此,现在,您可以在运行时使用一种备份策略创建服务,甚至还可以在运行时更改策略!Chekit出来:

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


$service->setStrategy(new SFTPBackup());
$service->testConn($request, $request->input('port'));
Run Code Online (Sandbox Code Playgroud)

您所有的封装算法都将在BackupStrategy类中收敛,但是请不要忘记所有这些“封装”

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

希望对您有帮助!