Definition
Define the skeleton of an algorithm in an operation, deferring some stepsto subclasses. Template Method lets subclasses redefine certain stepsof an algorithm without changing the algorithm's structure.
UML Class Diagram
Participants
The classes and/or objects participating in this pattern are:
-
AbstractClass(DataObject)
- Defines abstract primitive operations that concrete subclasses define to implement steps of an algorithm
- Implements a template method defining the skeleton of an algorithm. The template method calls primitive operations as well as operations defined in AbstractClass or those of other objects
-
ConcreteClass(CustomerDataObject)
- Implements the primitive operations or carry out subclass-specific steps of the algorithm
Sample Code in C#
This
structural code demonstrates the Template method which provides a skeleton calling sequence of methods. One or more steps can be deferred to subclasses which implement these steps without changing the overall calling sequence.
// Template Method pattern - Structural example
namespace CSharpLearning
{
using System;
/// <summary>
/// Startup class for Real-World Template Method design pattern.
/// </summary>
public class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
public static void Main()
{
AbstractClass aA = new ConcreteClassA();
aA.TemplateMethod();
AbstractClass aB = new ConcreteClassB();
aB.TemplateMethod();
// Wait for user.
Console.ReadKey();
}
}
/// <summary>
/// The 'AbstractClass' abstract class.
/// </summary>
public abstract class AbstractClass
{
/// <summary>
/// The primitive operation 1.
/// </summary>
public abstract void PrimitiveOperation1();
/// <summary>
/// The primitive operation 2.
/// </summary>
public abstract void PrimitiveOperation2();
/// <summary>
/// The template method.
/// </summary>
public void TemplateMethod()
{
this.PrimitiveOperation1();
this.PrimitiveOperation2();
Console.WriteLine(string.Empty);
}
}
/// <summary>
/// A 'ConcreteClass' class.
/// </summary>
public class ConcreteClassA : AbstractClass
{
/// <summary>
/// The primitive operation 1.
/// </summary>
public override void PrimitiveOperation1()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation1()");
}
/// <summary>
/// The primitive operation 2.
/// </summary>
public override void PrimitiveOperation2()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation2()");
}
}
/// <summary>
/// A 'ConcreteClass' class.
/// </summary>
public class ConcreteClassB : AbstractClass
{
/// <summary>
/// The primitive operation 1.
/// </summary>
public override void PrimitiveOperation1()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation1()");
}
/// <summary>
/// The primitive operation 2.
/// </summary>
public override void PrimitiveOperation2()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation2()");
}
}
}
// Output:
/*
ConcreteClassA.PrimitiveOperation1()
ConcreteClassA.PrimitiveOperation2()
ConcreteClassB.PrimitiveOperation1()
ConcreteClassB.PrimitiveOperation2()
*/
This
real-world code demonstrates a Template method named Run() which provides a skeleton calling sequence of methods. Implementation of these steps are deferred to the CustomerDataObject subclass which implements the Connect, Select, Process, and Disconnect
methods.// Template Method pattern - Real World example
namespace CSharpLearning
{
using System;
using System.Data;
using System.Data.OleDb;
/// <summary>
/// Startup class for Real-World Template Design Pattern.
/// </summary>
public class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
public static void Main()
{
DataAccessObject daoCategories = new Categories();
daoCategories.Run();
DataAccessObject daoProducts = new Products();
daoProducts.Run();
// Wait for user.
Console.ReadKey();
}
}
/// <summary>
/// The 'AbstractClass' abstract class.
/// </summary>
public abstract class DataAccessObject
{
/// <summary>
/// The connection string.
/// </summary>
protected string ConnectionString;
/// <summary>
/// The data set.
/// </summary>
protected DataSet DataSet;
/// <summary>
/// The connect.
/// </summary>
public virtual void Connect()
{
// Make sure mdb is available to app.
this.ConnectionString = "provider=Microsoft.JET.OLEDB.4.0; data source=..\\..\\..\\db1.mdb";
}
/// <summary>
/// The select.
/// </summary>
public abstract void Select();
/// <summary>
/// The process.
/// </summary>
public abstract void Process();
/// <summary>
/// The disconnect.
/// </summary>
public virtual void Disconnect()
{
this.ConnectionString = string.Empty;
}
/// <summary>
/// The 'Template Method'.
/// </summary>
public void Run()
{
this.Connect();
this.Select();
this.Process();
this.Disconnect();
}
}
/// <summary>
/// A 'ConcreteClass' class.
/// </summary>
public class Categories : DataAccessObject
{
/// <summary>
/// The select.
/// </summary>
public override void Select()
{
const string Sql = "select CategoryName from Categories";
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(Sql, this.ConnectionString);
this.DataSet = new DataSet();
dataAdapter.Fill(this.DataSet, "Categories");
}
/// <summary>
/// The process.
/// </summary>
public override void Process()
{
Console.WriteLine("Categories ---- ");
DataTable dataTable = this.DataSet.Tables["Categories"];
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["CategoryName"]);
}
Console.WriteLine();
}
}
/// <summary>
/// A 'ConcreteClass' class.
/// </summary>
public class Products : DataAccessObject
{
/// <summary>
/// The select.
/// </summary>
public override void Select()
{
const string Sql = "select ProductName from Products";
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(Sql, this.ConnectionString);
this.DataSet = new DataSet();
dataAdapter.Fill(this.DataSet, "Products");
}
/// <summary>
/// The process.
/// </summary>
public override void Process()
{
Console.WriteLine("Products ---- ");
DataTable dataTable = this.DataSet.Tables["Products"];
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["ProductName"]);
}
Console.WriteLine();
}
}
}
// Output:
/*
Categories ----
Beverages
Condiments
Confections
Dairy Products
Grains/Cereals
Meat/Poultry
Produce
Seafood
Products ----
Chai
Chang
Aniseed Syrup
Chef Anton's Cajun Seasoning
Chef Anton's Gumbo Mix
Grandma's Boysenberry Spread
Uncle Bob's Organic Dried Pears
Northwoods Cranberry Sauce
Mishi Kobe Niku
*/
分享到:
相关推荐
design-pattern-java.pdf
Design pattern In JavaScrip-design-pattern-in-javascript
JAVA design pattern-java设计模式.chm
算法的封装与切换——策略模式(四) 模板方法模式-Template Method Pattern 模板方法模式深度解析(一) 模板方法模式深度解析(二) 模板方法模式深度解析(三) 访问者模式-Visitor Pattern 操作复杂对象结构——...
C++11全套设计模式-23种指针的用法(a full DesignPattern -DesignPattern
DESIGN PATTERN - Pro Design Patterns in Swift,學習移動開發原始碼最佳選擇
design-pattern-java
个人觉得这本书介绍的设计模式知识比较通俗易懂
课程作业,adapter pattern基本演示
23种设计模式的C++实现DesignPattern-master.zip
design-pattern-demo
设计模式(21)-Template Method Pattern 设计模式(20)-Visitor Pattern 设计模式(19)-Observer Pattern 设计模式(18)-Command Pattern 设计模式(17)-Chain of Responsibility Pattern 设计模式(16)...
设计面向对象软件比较困难,而设计可复用的面向对象软件就更加困难。你必须找到相 关的对象,以适当的粒度将它们归类,再定义类的接口和继承层次,建立对象之间的基本关 系。你的设计应该对手头的问题有针对性,同时...
设计模式pdf
when it can be applied in view of other design constraints, and the consequences and trade-offs of using the pattern within a larger design. All patterns are compiled from real systems and are based ...
23种设计模式
Unity-Design-Pattern-master.zip.zip
经典的Java模式,工厂模式、单例模式,非常有助于初学者的学习
save document! UML file for the design pattern.
设计模式/design-pattern-lessons.pdf,设计模式包交不包会