如果您正在对接口进行编程,那么最灵活的选择是使用装饰器:
interface ILogger
{
function log($msg);
}
class FileLogger implements ILogger{
function log($msg)
{
file_put_contents('file.dat', $msg . "\n", FILE_APPEND);
}
}
interface IChecker
{
function check($var);
}
class Checker implements IChecker {
function check($var)
{
//do some checking
return true;
}
}
//decorator
class LoggingChecker implements IChecker
{
private $checker;
private $logger;
function __construct(IChecker $checker, ILogger $logger)
{
$this->checker = $checker;
$this->logger = $logger;
}
function check($var)
{
$checkResult = $this->checker->check($var);
$this->logger->log('check result is: ' . ($checkResult)? 'a success' : 'a failure');
return $checkResult;
}
}
interface IOperations
{
function doOperation($var);
}
class Operations implements IOperations{
private $checker;
function __construct(IChecker $checker)
{
$this->checker = $checker;
}
function doOperation($var)
{
if($this->checker->check($var)){
//do some operation
}
}
}
//composotion root
//create concrete logger, in this case a FileLogger instance, though you could latter create a SqlLogger or EmailLogger
//and swap it without any changes to the other classes
$logger = new FileLogger();
//create concreate checker
$checker = new Checker();
//create decorated checker
$loggingChecker = new LoggingChecker($checker, $logger);
//Operations can now be instantiated with either the regular checker, or the decorated logging checker, and it will
//work just the same, with no knowledge of the existense of loging, or indeed any knowledge of how the checker functions, beyond
//the fact it has a method called check that excepts a single parameter
$operation = new Operations($checker); //no logging is done
//OR
$operation = new Operations($loggingChecker); //logging is done
请注意,在上面的示例中,我只为IChecker 创建了一个装饰器。
您还可以为IOperations 创建一个装饰器,例如LoggingOperations,其工作方式相同——它依赖于ILogger 和IOperations 的实例。
您将使用相同的具体 ILogger 实现 ($logger) 和 IOperations 实现 ($operation) 来实例化它。
使用该对象的类对IOperations 具有单一依赖关系,可以使用$operation 或$logginOperation 进行实例化,并且行为方式相同。
希望这个示例让您了解接口编程的灵活性以及装饰器模式如何简化依赖类并帮助实施 SRP