2016-10-28 3 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 
    } 
} 

Как мне нужны такие вещи, как «сервис» и порт, назначенный во время выполнения, IM используя «стратегический шаблон» для достижения этого, например.

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

В дополнение к Саймон и Лоран.

Вы используете интерфейсы, поэтому реализация должна соответствовать.

Возможное решение:

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, добавив логику в конструктор. Thats not good.

Вы можете сделать подклассы, каждый из которых реализует реализацию (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')); 

Тогда вы могли бы реализовать переключатель во время выполнения.

Кроме того, вы могли бы сделать метод setStrategy в классе BackupStrategy, которые устанавливают или изменения стратегии резервного копирования во время выполнения:

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, где все ваши инкапсулированные алгоритмы будут сходиться, но дон забыть «инкапсуляция» во всем этом!

Наиболее важным в шаблоне стратегии является инкапсуляция семейства алгоритмов, которые могут использоваться во время работы!

Надеюсь, это поможет вам!

Смежные вопросы