PHP design pattern series-chainofreelosibilities 1. Pattern Definition
In the responsible chain mode, the request object is connected into a chain, and the request is passed along this chain until one object processes the request. This gives multiple objects the opportunity to process the request, this avoids the coupling between request senders and receivers.
In reality, the responsibility chain model is used in many ways. common tasks are workflows in the OA system.
2. UML class diagram
3. Sample Code Request. php
Handler. php
Successor) {$ this-> successor = $ handler;} else {$ this-> successor-> append ($ handler );}} /*** process the request ** This approach by using a template method pattern ensures you that * each subclass will not forget to call the successor. besides, the returned * boolean value indicates you if the request have been processed or not. ** @ param Request $ req ** @ return bool */final public function handle (Reque St $ req) {$ req-> forDebugOnly = get_called_class (); $ processed = $ this-> processing ($ req); if (! $ Processed) {// the request has not been processed by this handler => see the next if (! Is_null ($ this-> successor) {$ processed = $ this-> successor-> handle ($ req) ;}} return $ processed ;} /*** each processor must implement this method to process the Request. ** @ param request $ req ** @ return bool true if the Request has been processed */abstract protected function processing (Request $ req );}
Responsible/SlowStorage. php
data = $data; } protected function processing(Request $req) { if ('get' === $req->verb) { if (array_key_exists($req->key, $this->data)) { $req->response = $this->data[$req->key]; return true; } } return false; }}
Responsible/FastStorage. php
data = $data; } protected function processing(Request $req) { if ('get' === $req->verb) { if (array_key_exists($req->key, $this->data)) { // the handler IS responsible and then processes the request $req->response = $this->data[$req->key]; // instead of returning true, I could return the value but it proves // to be a bad idea. What if the value IS "false" ? return true; } } return false; }}
4. test code Tests/ChainTest. php
chain = new FastStorage(array('bar' => 'baz')); $this->chain->append(new SlowStorage(array('bar' => 'baz', 'foo' => 'bar'))); } public function makeRequest() { $request = new Request(); $request->verb = 'get'; return array( array($request) ); } /** * @dataProvider makeRequest */ public function testFastStorage($request) { $request->key = 'bar'; $ret = $this->chain->handle($request); $this->assertTrue($ret); $this->assertObjectHasAttribute('response', $request); $this->assertEquals('baz', $request->response); // despite both handle owns the 'bar' key, the FastStorage is responding first $className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage'; $this->assertEquals($className, $request->forDebugOnly); } /** * @dataProvider makeRequest */ public function testSlowStorage($request) { $request->key = 'foo'; $ret = $this->chain->handle($request); $this->assertTrue($ret); $this->assertObjectHasAttribute('response', $request); $this->assertEquals('bar', $request->response); // FastStorage has no 'foo' key, the SlowStorage is responding $className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage'; $this->assertEquals($className, $request->forDebugOnly); } /** * @dataProvider makeRequest */ public function testFailure($request) { $request->key = 'kurukuku'; $ret = $this->chain->handle($request); $this->assertFalse($ret); // the last responsible : $className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage'; $this->assertEquals($className, $request->forDebugOnly); }}
5. SummaryThe main advantage of the responsibility chain mode is that it can reduce the coupling degree of the system, simplify the connection between objects, increase the flexibility of assigning responsibilities to objects, and add new request processing classes; the main drawback is that the request cannot be received, and for a long responsibility chain, the request processing may involve multiple processing objects, and the system performance will be affected, it is not convenient for code debugging.