当用户将鼠标光标指向某个元素并按下 当用户将鼠标光标指向某个元素并按下 F1 键时,应用程序将检测指针下的组件并向其发送帮助请求。该请求将在元素的所有容器中冒泡,直到到达能够显示帮助信息的元素。 键时,应用程序将检测指针下的组件并向其发送帮助请求。该请求将在元素的所有容器中冒泡,直到到达能够显示帮助信息的元素。
// The handler interface declares a method for executing a // request. interfaceComponentWithContextualHelp is method showHelp()
// The base class for simple components. abstractclassComponentimplementsComponentWithContextualHelp is field tooltipText: string
// The component's container acts as the next link in the // chain of handlers. protected field container: Container
// The component shows a tooltip if there's help text // assigned to it. Otherwise it forwards the call to the // container, if it exists. method showHelp() is if(tooltipText != null) // Show tooltip. else container.showHelp()
// Containers can contain both simple components and other // containers as children. The chain relationships are // established here. The class inherits showHelp behavior from // its parent. abstractclassContainerextendsComponent is protected field children: array of Component
method add(child) is children.add(child) child.container = this
// Primitive components may be fine with default help // implementation... classButtonextendsComponent is // ...
// But complex components may override the default // implementation. If the help text can't be provided in a new // way, the component can always call the base implementation // (see Component class). classPanelextendsContainer is field modalHelpText: string
method showHelp() is if(modalHelpText != null) // Show a modal window with the help text. else super.showHelp()
// ...same as above... classDialogextendsContainer is field wikiPageURL: string
method showHelp() is if(wikiPageURL != null) // Open the wiki help page. else super.showHelp()
// Client code. classApplication is // Every application configures the chain differently. method createUI()is dialog=newDialog("Budget Reports") dialog.wikiPageURL = "http://..." panel = newPanel(0, 0, 400, 800) panel.modalHelpText = "This panel does..." ok = newButton(250, 760, 50, 20, "OK") ok.tooltipText = "This is an OK button that..." cancel = newButton(320, 760, 50, 20, "Cancel") // ... panel.add(ok) panel.add(cancel) dialog.add(panel)
// Imagine what happens here. method onF1KeyPress()is component=this.getComponentAtMouseCoords() component.showHelp()
from __future__ import annotations from abc import ABC, abstractmethod from typing importAny, Optional
classHandler(ABC): """ The Handler interface declares a method for building the chain of handlers. It also declares a method for executing a request. """
classAbstractHandler(Handler): """ The default chaining behavior can be implemented inside a base handler class. """
_next_handler: Handler = None
defset_next(self, handler: Handler) -> Handler: self._next_handler = handler # Returning a handler from here will let us link handlers in a # convenient way like this: # monkey.set_next(squirrel).set_next(dog) return handler
@abstractmethod defhandle(self, request: Any) -> str: if self._next_handler: return self._next_handler.handle(request)
returnNone
""" All Concrete Handlers either handle a request or pass it to the next handler in the chain. """
classMonkeyHandler(AbstractHandler): defhandle(self, request: Any) -> str: if request == "Banana": returnf"Monkey: I'll eat the {request}" else: returnsuper().handle(request)
classSquirrelHandler(AbstractHandler): defhandle(self, request: Any) -> str: if request == "Nut": returnf"Squirrel: I'll eat the {request}" else: returnsuper().handle(request)
classDogHandler(AbstractHandler): defhandle(self, request: Any) -> str: if request == "MeatBall": returnf"Dog: I'll eat the {request}" else: returnsuper().handle(request)
defclient_code(handler: Handler) -> None: """ The client code is usually suited to work with a single handler. In most cases, it is not even aware that the handler is part of a chain. """
for food in ["Nut", "Banana", "Cup of coffee"]: print(f"\nClient: Who wants a {food}?") result = handler.handle(food) if result: print(f" {result}", end="") else: print(f" {food} was left untouched.", end="")
if __name__ == "__main__": monkey = MonkeyHandler() squirrel = SquirrelHandler() dog = DogHandler()
monkey.set_next(squirrel).set_next(dog)
# The client should be able to send a request to any handler, not just the # first one in the chain. print("Chain: Monkey > Squirrel > Dog") client_code(monkey) print("\n")
Client: Who wants a Nut? Squirrel: I'll eat the Nut Client: Who wants a Banana? Monkey: I'll eat the Banana Client: Who wants a Cup of coffee? Cup of coffee was left untouched.
Subchain: Squirrel > Dog
Client: Who wants a Nut? Squirrel: I'll eat the Nut Client: Who wants a Banana? Banana was left untouched. Client: Who wants a Cup of coffee? Cup of coffee was left untouched.
/// A single role of objects that make up a chain. /// A typical trait implementation must have `handle` and `next` methods, /// while `execute` is implemented by default and contains a proper chaining /// logic. pubtraitDepartment { fnexecute(&mutself, patient: &mut Patient) { self.handle(patient);
implDepartmentforMedical { fnhandle(&mutself, patient: &mut Patient) { if patient.medicine_done { println!("Medicine is already given to a patient"); } else { println!("Medical giving medicine to a patient {}", patient.name); patient.medicine_done = true; } }
// Reception handles a patient passing him to the next link in the chain. // Reception -> Doctor -> Medical -> Cashier. reception.execute(&mut patient);
println!("\nThe patient has been already handled:\n");
reception.execute(&mut patient); }
输出
1 2 3 4 5 6 7 8 9 10 11
Reception registering a patient John Doctor checking a patient John Medical giving medicine to a patient John Cashier getting money from a patient John
The patient has been already handled:
Patient registration is already done A doctor checkup is already done Medicine is already given to a patient Payment done