Reputation: 4055
I was wondering if i could get a bit of help.
I have an interface like so
interface BackupContract {
public function testConn($request, $port);
}
Then the 2 example implementations of this interface is as follows
class FTPBackup implements BackupContract {
public function testConn($request, $port = 21) {
// code here
}
}
class SFTPBackup implements BackupContract {
public function testConn($request, $port = 22) {
// code here
}
}
As i need things like 'service' and port designated at runtime, im using 'strategy pattern' to achieve this, like so.
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);
}
}
and finally, in my controller im using the following code to put it all together.
$service = new BackupStrategy($request->input('service'));
$service->testConn($request, $request->input('port'));
The problem is, that if a user doesnt enter a port, it is meant to auto assign a port variable, i.e 21 or 22 like in the 2 implementations.
It doesn't seem to be working, but its not throwing any errors
Upvotes: 2
Views: 2515
Reputation: 51
But you shouldnt implement the switch in the BackupStrategy's constructor.
With your aproach, you are violating the "open/close" principle from the S.O.L.I.D 's principles.
Any time you need to add another "backup strategy" you need to modify the BackupStrategy class, adding the logic to the constructor. Thats not good.
You could make sublcasses, each implementig the implementation (LOL) of each backup strategy classes and only inherating the necessary from BackupStrategy class.
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'));
Or even this:
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'));
Then you could implement the switch during runtime.
Also you could make a setStrategy method in BackupStrategy class that set or change the backup strategy during runtime:
public function setStrategy(BackupContract $bc)
{
$this->strategy = $bc();
}
So now, you can create a service with one backup strategy during runtime, and even change the strategy during runtime also!! Chekit out:
$service = new BackupStrategy(new FTPBackup());
$service->testConn($request, $request->input('port'));
$service->setStrategy(new SFTPBackup());
$service->testConn($request, $request->input('port'));
The BackupStrategy class is where all your encapsulated algorithms will converge, but don forget the "encapsulation" in all this!
The most important in the Strategy Pattern is the encapsulation of a family of algorithms that can be used during runtime!
Hope it helps you!
Upvotes: 5
Reputation: 5806
In addition to Simon and Laurent.
You're using interfaces, so the implementation should match.
A possible solution:
interface BackupContract {
public function testConn($request, $port = 0);
}
But personally, I don't prefer this approach. Optional things in interfaces means that you should validate in possible each implementation instead of trusting the implementation.
Secondly, I recommend using type declarations (PHP7), for example:
public function foo(int $bar) : bool
{
return true;
}
This method expects an integer as argument (must) and a boolean value as return (must). Using $bar, you are sure that this var type is an integer.
See for more information: http://php.net/manual/en/migration70.new-features.php
Upvotes: 1
Reputation: 191
You are always setting a port in BackupStrategy->testConn($request, $port)
method. So if somebody doesn't give a port, it will pass an empty string.
I would implement a fallback function.
And what @simon said, you are using the wrong method name in your controller.
Upvotes: 0
Reputation: 2946
You are calling a testConnection();
method which doesn't exist. What you actually want to call is testConn();
Check your error reporting settings because this should definitely throw an error.
Upvotes: 0