Started by Peter Lewerin (2003-08-17).
IANAPG (I am not a patterns guru), so I use the example code from http://www.dofactory.com/Patterns/Patterns.aspx as a base for my implementations.
Chain-of-responsibility: "Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it."
package require snit snit::type handler { option -handleIf variable condition false onconfigure -handleIf value {set condition $value} option -handleBy variable consequent {} onconfigure -handleBy value {set consequent $value} option -elseReportTo variable alternative {} onconfigure -elseReportTo value { set alternative [concat $value handle \$request] } method handle request { if $condition $consequent $alternative } }
Example:
proc main args { handler Tom -handleIf { $request >= 0 && $request < 10 } -handleBy { puts "$self handled request $request" } -elseReportTo Gus handler Gus -handleIf { $request >= 10 && $request < 20 } -handleBy { puts "$self handled request $request" } -elseReportTo Mary handler Mary -handleIf { $request >= 20 && $request < 30 } -handleBy { puts "$self handled request $request" } foreach request [list 2 5 14 22 18 38 3 27 20] { Tom handle $request } }
Command: "Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations."
package require snit snit::type command { option -calculator option -operator option -operand method execute {} { [$self cget -calculator] operation [$self cget -operator] [$self cget -operand] } method unexecute {} { set inverseOperator [string map {+ - - + * / / *} [$self cget -operator]] [$self cget -calculator] operation $inverseOperator [$self cget -operand] } } snit::type receiver { variable accumulator 0 method operation {operator operand} { set accumulator [expr [list $accumulator $operator $operand]] puts "Total = $accumulator (following $operator $operand)" } } snit::type invoker { variable calculator variable commands variable current 0 method redo levels { puts "---- Redo $levels levels" for {set i 0} {$i < $levels} {incr i} { if {$current < [llength $commands]} { [lindex $commands $current] execute incr current } } } method undo levels { puts "---- Undo $levels levels" for {set i 0} {$i < $levels} {incr i} { if {$current > 0} { [lindex $commands [incr current -1]] unexecute } } } method compute {operator operand} { set command [command %AUTO% \ -calculator $calculator \ -operator $operator \ -operand $operand] $command execute lappend commands $command incr current } constructor args { set calculator [receiver %AUTO%] } }
Example:
proc main args { invoker user user compute + 100 user compute - 50 user compute * 10 user compute / 2 user undo 4 user redo 3 }