The purpose of the chain of responsibility pattern is to organize a chain of objects to handle a request such as a method call.
When the ConcreteHandler (specific handler) does not know how to satisfy the request from the Client, or its purpose is not this, it will be delegated to the next Handler (handler) in the chain for processing.
This design pattern is often used in conjunction with the Composite pattern, where some leaf or container objects delegate operations to their parent objects by default. Another example is that localization is often handled using a chain of responsibility, where when the German translation adapter does not find suitable results for a translated keyword, it falls back to the English adapter or simply displays the keyword itself.
Coupling is reduced to a minimum: the Client class does not know which specific class handles the request; the chain is configured when creating the object graph; ConcreteHandlers do not know which object is their inheritor. Behavior is distributed successfully among objects, and the object closest in the chain has priority and responsibility for fulfilling the request.
Participants:
◆Client (client): Submit a request to Handler (handler);
◆Handler (handler) Abstract: Receive a request, satisfy it in some way;
◆ConcreteHandlers (concrete handlers): Receive a request, try to satisfy it, and delegate to the next handler if unsuccessful.
The following code implements one of the most famous examples of chain of responsibility: multi-level caching.
Copy code The code is as follows:
/**
* The Handler abstraction. Objects that want to be a part of the
* ChainOfResponsibility must implement this interface directly or via
* inheritance from an AbstractHandler.
*/
interface KeyValueStore
{
/**
* Obtain a value.
* @param string $key
* @return mixed
*/
public function get($key);
}
/**
* Basic no-op implementation which ConcreteHandlers not interested in
* caching or in interfering with the retrieval inherit from.
*/
abstract class AbstractKeyValueStore implements KeyValueStore
{
protected $_nextHandler;
public function get($key)
{
return $this->_nextHandler->get($key);
}
}
/**
* Ideally the last ConcreteHandler in the chain. At least, if inserted in
* a Chain it will be the last node to be called.
*/
class SlowStore implements KeyValueStore
{
/**
* This could be a somewhat slow store: a database or a flat file.
*/
protected $_values;
public function __construct(array $values = array())
{
$this->_values = $values;
}
public function get($key)
{
return $this->_values[$key];
}
}
/**
* A ConcreteHandler that handles the request for a key by looking for it in
* its own cache. Forwards to the next handler in case of cache miss.
*/
class InMemoryKeyValueStore implements KeyValueStore
{
protected $_nextHandler;
protected $_cached = array();
public function __construct(KeyValueStore $nextHandler)
{
$this->_nextHandler = $nextHandler;
}
protected function _load($key)
{
if (!isset($this->_cached[$key])) {
$this->_cached[$key] = $this->_nextHandler->get($key);
}
}
public function get($key)
{
$this->_load($key);
return $this->_cached[$key];
}
}
/**
* A ConcreteHandler that delegates the request without trying to
* understand it at all. It may be easier to use in the user interface
* because it can specialize itself by defining methods that generates
* html, or by addressing similar user interface concerns.
* Some Clients see this object only as an instance of KeyValueStore
* and do not care how it satisfy their requests, while other ones
* may use it in its entirety (similar to a class-based adapter).
* No client knows that a chain of Handlers exists.
*/
class FrontEnd extends AbstractKeyValueStore
{
public function __construct(KeyValueStore $nextHandler)
{
$this->_nextHandler = $nextHandler;
}
public function getEscaped($key)
{
return htmlentities($this->get($key), ENT_NOQUOTES, 'UTF-8');
}
}
// Client code
$store = new SlowStore(array('pd' => 'Philip K. Dick',
'ia' => 'Isaac Asimov',
'ac' => 'Arthur C. Clarke',
'hh' => 'Helmut Heißenbüttel'));
// in development, we skip cache and pass $store directly to FrontEnd
$cache = new InMemoryKeyValueStore($store);
$frontEnd = new FrontEnd($cache);
echo $frontEnd->get('ia'), "n";
echo $frontEnd->getEscaped('hh'), "n";
Some implementation notes about the PHP chain of responsibility design pattern:
◆The chain of responsibility may already exist in the object graph, as in the composite pattern example;
◆In addition, the Handler abstraction may or may not exist. The best choice is a separate Handler interface that can only perform handleRequest() operations. Do not force a chain to only be in one level, because the latter ones already exist;
◆It is also possible to introduce an abstract class, but since request processing is an orthogonal concern, the specific class may have inherited other classes;
◆Through the constructor or setter, the Handler (or the next Handler) is injected into the Client Or the previous Handler;
◆The request object is usually a ValueObject, which may also be implemented as a Flyweight. In PHP, it may be a scalar type, such as string. Note that in some languages, a string is not a Variable ValueObject.
A simple summary of the chain of responsibility model can be summarized as: using a series of classes to try to handle a request. There is a loose coupling between these classes. The only thing in common is to pass the request between them. . In other words, when a request comes, Class A processes it first. If it is not processed, it is passed to Class B for processing. If it is not processed, it is passed to Class C for processing, and it is passed on like a chain.
http://www.bkjia.com/PHPjc/327557.htmlwww.bkjia.comtruehttp: //www.bkjia.com/PHPjc/327557.htmlTechArticleThe chain of responsibility model is designed to organize an object chain to handle a request such as a method call. When the ConcreteHandler (specific handler) does not know how to satisfy the request from the Client,...