-
Notifications
You must be signed in to change notification settings - Fork 0
Chain Of Responsibility
The client (sender) needs to handle some operation but the implementation of this operation may vary, if client decides so. Furthermore, the operations may consist of the sequence (defined by client during the runtime) of other small operations.
If the operation may vary from time to time, it may be considered as the strategy, and in the same way as in a Strategy pattern, the operation may be encapsulated in the separate object, or a complex of separate objects, which are implementing the same interface (so the sender may use the advantages of polymorphism and may know nothing about the concrete object). In other words, the object delegates the operation to the class of different objects. However, it doesn't solve the problem of sequencing the operations. The solution is to implement the receiving object in such way, so it can delegate the part of (or whole) operation to the other object of the same class of receivers. The operation may be implemented in this way:
- If client will send the data, which must be processed by this receiver specifically - it will do it's job and return the results.
- If the concrete receiver is responsible only for the part of the job - it will process the data and send the results to its next receiver object (which will be specified by client ahead).
- If this receiver is not responsible for operation at all - it will just pass the received data to the next receiver directly.
The client can set the sequence of operations by just declaring the next receiver for each receiver (making the chain of them). Then he will only have to pass the data to the first receiver in a chain and it will process it or delegate the process to the next receiver in chain. As a result the sender will get the one-method interface for operations, and every receiver must implement only the mutator of its next receiver and the method which will be doing the operation.
- Sender - the delegator object (or client itself) which defines the next receiver for every receiver and creates the request to the first receiver, by running its handle operation method.
- Receiver - the class of objects which are encapsulating the operations logic, have the next receiver mutators and are implementing the operation method, which executes the operation and/or delegates the request to the next receiver object.
polymorphism delegation encapsulation
The editorial office of a local magazine has a lot of departments. Each department prepared its own article so the chief editor must decide in which order to assemble them and to declare the sequence of delivery of finished materials.
Department - the abstract singleton class which implements the methods of Receiver. SportsDepartment, NewsDepartment, CultureDepartment, InvestigationsDepartment, PrintDepartment - the concrete singleton implementations of Department. EditorialOrder - the object, which encapsulates the request data.
I've decided to keep it simple and not to design the concrete receivers in a way it must be instantiated. In my example each class is already the receiver object with its own predefined data and operations. Client may specify the chain of departments (even make the recursive chain), by running the .next_receiver= methods of them, and execute the operations by running .handle method on any of them, passing the EditorialOrder object with operations type sequence, set as parameters (read the implementation.rb file).