// The abstract class defines a template method that contains a // skeleton of some algorithm composed of calls, usually to // abstract primitive operations. Concrete subclasses implement // these operations, but leave the template method itself // intact. classGameAI is // The template method defines the skeleton of an algorithm. method turn() is collectResources() buildStructures() buildUnits() attack()
// Some of the steps may be implemented right in a base // class. method collectResources() is foreach(s in this.builtStructures)do s.collect()
// And some of them may be defined as abstract. abstract method buildStructures() abstract method buildUnits()
// A class can have several template methods. method attack()is enemy= closestEnemy() if (enemy == null) sendScouts(map.center) else sendWarriors(enemy.position)
// Concrete classes have to implement all abstract operations of // the base class but they must not override the template method // itself. classOrcsAIextendsGameAI is method buildStructures() is if(there are some resources) then // Build farms, then barracks, then stronghold.
method buildUnits() is if(there are plenty of resources) then if(there are no scouts) // Build peon, add it to scouts group. else // Build grunt, add it to warriors group.
// ...
method sendScouts(position) is if(scouts.length > 0) then // Send scouts to position.
method sendWarriors(position) is if(warriors.length > 5) then // Send warriors to position.
// Subclasses can also override some operations with a default // implementation. classMonstersAIextendsGameAI is method collectResources() is // Monsters don't collect resources.
method buildStructures() is // Monsters don't build structures.
method buildUnits() is // Monsters don't build units.
classAbstractClass(ABC): """ The Abstract Class defines a template method that contains a skeleton of some algorithm, composed of calls to (usually) abstract primitive operations. Concrete subclasses should implement these operations, but leave the template method itself intact. """
deftemplate_method(self) -> None: """ The template method defines the skeleton of an algorithm. """
# These are "hooks." Subclasses may override them, but it's not mandatory # since the hooks already have default (but empty) implementation. Hooks # provide additional extension points in some crucial places of the # algorithm.
defhook1(self) -> None: pass
defhook2(self) -> None: pass
classConcreteClass1(AbstractClass): """ Concrete classes have to implement all abstract operations of the base class. They can also override some operations with a default implementation. """
defclient_code(abstract_class: AbstractClass) -> None: """ The client code calls the template method to execute the algorithm. Client code does not have to know the concrete class of an object it works with, as long as it works with objects through the interface of their base class. """
# ... abstract_class.template_method() # ...
if __name__ == "__main__": print("Same client code can work with different subclasses:") client_code(ConcreteClass1()) print("")
print("Same client code can work with different subclasses:") client_code(ConcreteClass2())
输出.txt:执行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Same client code can work with different subclasses: AbstractClass says: I am doing the bulk of the work ConcreteClass1 says: Implemented Operation1 AbstractClass says: But I let subclasses override some operations ConcreteClass1 says: Implemented Operation2 AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses: AbstractClass says: I am doing the bulk of the work ConcreteClass2 says: Implemented Operation1 AbstractClass says: But I let subclasses override some operations ConcreteClass2 says: Overridden Hook1 ConcreteClass2 says: Implemented Operation2 AbstractClass says: But I am doing the bulk of the work anyway
fnmain() { println!("Same client code can work with different concrete implementations:"); client_code(ConcreteStruct1); println!();
println!("Same client code can work with different concrete implementations:"); client_code(ConcreteStruct2); }
Output 输出
1 2 3 4 5 6 7 8 9 10 11 12 13
Same client code can work with different concrete implementations: TemplateMethod says: I am doing the bulk of the work ConcreteStruct1 says: Implemented Operation1 TemplateMethod says: But I let subclasses override some operations ConcreteStruct1 says: Implemented Operation2 TemplateMethod says: But I am doing the bulk of the work anyway
Same client code can work with different concrete implementations: TemplateMethod says: I am doing the bulk of the work ConcreteStruct2 says: Implemented Operation1 TemplateMethod says: But I let subclasses override some operations ConcreteStruct2 says: Implemented Operation2 TemplateMethod says: But I am doing the bulk of the work anyway