namespaceRefactoringGuru.DesignPatterns.TemplateMethod.Conceptual { // 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. abstractclassAbstractClass { // The template method defines the skeleton of an algorithm. publicvoidTemplateMethod() { this.BaseOperation1(); this.RequiredOperations1(); this.BaseOperation2(); this.Hook1(); this.RequiredOperation2(); this.BaseOperation3(); this.Hook2(); }
// These operations already have implementations. protectedvoidBaseOperation1() { Console.WriteLine("AbstractClass says: I am doing the bulk of the work"); }
protectedvoidBaseOperation2() { Console.WriteLine("AbstractClass says: But I let subclasses override some operations"); }
protectedvoidBaseOperation3() { Console.WriteLine("AbstractClass says: But I am doing the bulk of the work anyway"); }
// These operations have to be implemented in subclasses. protectedabstractvoidRequiredOperations1();
protectedabstractvoidRequiredOperation2();
// 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. protectedvirtualvoidHook1() { }
protectedvirtualvoidHook2() { } }
// Concrete classes have to implement all abstract operations of the base // class. They can also override some operations with a default // implementation. classConcreteClass1 : AbstractClass { protectedoverridevoidRequiredOperations1() { Console.WriteLine("ConcreteClass1 says: Implemented Operation1"); }
classClient { // 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. publicstaticvoidClientCode(AbstractClass abstractClass) { // ... abstractClass.TemplateMethod(); // ... } }
classProgram { staticvoidMain(string[] args) { Console.WriteLine("Same client code can work with different subclasses:");
Client.ClientCode(new ConcreteClass1());
Console.Write("\n");
Console.WriteLine("Same client code can work with different subclasses:"); Client.ClientCode(new ConcreteClass2()); } } }
执行结果:
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