Click here to Skip to main content
Click here to Skip to main content

Recoding Using the Template Method Design Pattern

, 29 May 2007
Rate this:
Please Sign up or sign in to vote.
This article shows a recoding sample using the Template Method Design Pattern.

Introduction

I recently recognized the importance of Design Patterns so started to change my non-design-pattern-code to design-pattern-code. In this part, I introduce an example that adapts the Template Method Design Pattern, but I don't know whether this is good or bad. I look forward to listening to your opinions.

Background

The Template Method Design Pattern defines the program skeleton of an algorithm on a Template Method of an abstract class. Child classes instantiate this algorithm by implementing their own logic on the skeleton that is an abstract method provided by the abstract class.

Coding without considering a Design Pattern

The fuction InitCommonVariables() initializes two ArrayLists using filtering from the DataTable (dtMSTDLDTM) and repeats this work for another DataTable (dtMEVENT). You will figure out that the two initialization processes have the same algorithm.

/// Initialize Current Activity        
private void InitCommonVariables()
{
    // Get Selected Activity
    currentActivity = (Progress.Model.ProgressActivity)this.Activity;
    if (currentActivity.BNodeLevel == (int)ActivityNodeLevel.Kojun)
    {
        // Ready to Set ComboBox Items from M_STDLDTM DataTable
        dtMSTDLDTM = ((ProgressGanttModel)(currentActivity.GanttModel)).dtMSTDLDTM;
        if (dtMSTDLDTM.Rows.Count > 0)
        {
            // Set Primary Key of Table for Row Search
            System.Data.DataColumn[] primaryKey = new System.Data.DataColumn[1];
            primaryKey[0] = dtMSTDLDTM.Columns[0];
            dtMSTDLDTM.PrimaryKey = primaryKey;
            listWrkID = new ArrayList();
            listWrkNM = new ArrayList();
            // Set Filter
            String filter = "";
            if (initParams.scheduleType == EnumScheduleType.Mschedule)
            {
              filter = "SCH_TYP<>2";
            }
            else if (initParams.scheduleType == EnumScheduleType.Sschedule)
            {
              filter = "SCH_TYP=2";
            }
            filter = "(" + filter + ") AND (DEL_FLG<>1)";
            // Initialize ArrayList
            foreach (System.Data.DataRow row in dtMSTDLDTM.Select(filter))
            {
                listWrkID.Add(row["WRK_ID"].ToString());
                listWrkNM.Add(row["WRK_NM"].ToString());
            }
        }
        // If DataTable has no Column Add Columns for Error Handling
        if (dtMSTDLDTM.Columns.Count == 0)
        {
            System.Data.DataColumn wrkIDColumn = new System.Data.DataColumn("WRK_ID");
            System.Data.DataColumn wrkNMColumn = new System.Data.DataColumn("WRK_NM");
            dtMSTDLDTM.Columns.Add(wrkIDColumn);
            dtMSTDLDTM.Columns.Add(wrkNMColumn);
        }
        // Ready to Set ComboBox Items from M_EVENT DataTable
        if (currentActivity.BEventFlg == 1)
        {
            dtMEVENT = ((ProgressGanttModel)(currentActivity.GanttModel)).dtMEVENT;
            if (dtMEVENT.Rows.Count > 0)
            {
                // Set Primary Key of Table for Row Search
                primaryKey = new System.Data.DataColumn[1];
                primaryKey[0] = dtMEVENT.Columns[0];
                dtMEVENT.PrimaryKey = primaryKey;
                listEventID = new ArrayList();
                listEventNM = new ArrayList();
                // Initialize ArrayList
                foreach (System.Data.DataRow row in dtMEVENT.Rows)
                {
                    listEventID.Add(row["EVENT_ID"].ToString());
                    listEventNM.Add(row["EVENT_NM"].ToString());
                }
            }
            // If DataTable has no Column Add Columns for Error Handling
            if (dtMEVENT.Columns.Count == 0)
            {
                System.Data.DataColumn eventIDColumn = new System.Data.DataColumn("EVENT_ID");
                System.Data.DataColumn eventNMColumn = new System.Data.DataColumn("EVENT_NM");
                dtMEVENT.Columns.Add(eventIDColumn);
                dtMEVENT.Columns.Add(eventNMColumn);
            }
        }
    }
}

Using two ArrayLists, I initialize a ComboBox:

/// Set Work Name On KojunNameComboBox
private void SetItemsonKojunNameCombo(ComboBox comboBox, System.Data.DataTable dataSource)
{
    comboBox.DisplayMember = "WRK_NM";
    comboBox.ValueMember = "WRK_ID";
    System.Data.DataTable dataTable = getMStdLdTmFilterTbl(dataSource);
    // Set Value from DataTable
    comboBox.DataSource = dataTable;
    if (dataTable.Rows.Count > 0)
    {
        // Add Current Activty Item if not in M_STDLDTM Table
        int currentItemIndex = listWrkID.IndexOf(currentActivity.BWrkId);
        if (currentItemIndex >= 0)
        {
            // Change Work Name
            System.Data.DataTable displayTable = dataTable.Copy();
            displayTable.Rows[currentItemIndex]["WRK_NM"] = currentActivity.Name;
            comboBox.DataSource = displayTable;
            comboBox.SelectedIndex = currentItemIndex;
        }
        else
        {
            System.Data.DataTable displayTable = dataTable.Copy();
            System.Data.DataRow row = displayTable.NewRow();
            if (currentActivity.BWrkId != null)
            {
                row["WRK_ID"] = currentActivity.BWrkId;
            }
            else
            {
                row["WRK_ID"] = -1;
            }
            if (currentActivity.BWrkName != null)
            {
                row["WRK_NM"] = currentActivity.BWrkName;
            }
            else
            {
                // Set Empty
                row["WRK_NM"] = "";
            }
            displayTable.Rows.InsertAt(row, 0);
            comboBox.DataSource = displayTable;
            comboBox.SelectedIndex = 0;
        }
    }
    else
    {
        System.Data.DataTable displayTable = dataTable.Copy();
        displayTable.Clear();
        if (currentActivity.BWrkId != null)
        {
            System.Data.DataRow row = displayTable.NewRow();
            row["WRK_ID"] = currentActivity.BWrkId;
            row["WRK_NM"] = currentActivity.BWrkName;
            displayTable.Rows.Add(row);
        }
        comboBox.DataSource = displayTable;
        if (currentActivity.BWrkId != null)
        {
            comboBox.SelectedIndex = 0;
        }
    }
}

/// Set Event Name On EventNameComboBox
private void SetItemsonEventNameCombo(ComboBox comboBox, System.Data.DataTable dataSource)
{
    comboBox.DisplayMember = "EVENT_NM";
    comboBox.ValueMember = "EVENT_ID";
    // Set Value from DataTable
    comboBox.DataSource = dataSource;
    if (dataSource.Rows.Count > 0)
    {
        // Add Current Event Item if not in M_EVENT Table
        int currentItemIndex = -1;
        if (currentActivity.Name != null)
        {
            currentItemIndex = listEventNM.IndexOf(currentActivity.Name);
        }
        if (currentItemIndex >= 0)
        {
            // Show Current Tree's Event Name if Tree has a same EventID
            System.Data.DataTable displayTable = dataSource.Copy();
            //displayTable.Rows[currentItemIndex]["EVENT_NM"] = currentActivity.Name;
            comboBox.DataSource = displayTable;
            comboBox.SelectedIndex = currentItemIndex;
        }
    }
    // Set Event Items ReadOnly
    comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
}

Lastly, I save the selected item and the selected value from the ComboBox:

private void SaveKojunWorkNMandID()
{
    // T_SCH_WRK's WRK_NM
    currentActivity.BWrkName = kojunNameCombo.Text;
    // T_SCH_TREE's WRK_NM
    currentActivity.Name = kojunNameCombo.Text;
    
    // T_SCH_WRK's WRK_ID
    if (listWrkID.Contains(kojunNameCombo.SelectedValue))
    {
        int selectedIndex = listWrkID.IndexOf(kojunNameCombo.SelectedValue);
        if (selectedIndex >= 0)
        {
            // If not Changed
            if (kojunNameCombo.Text == (string)listWrkNM[selectedIndex])
            {
                currentActivity.BWrkId = (string)kojunNameCombo.SelectedValue;
            }
            else
            {
                currentActivity.BWrkId = "";
            }
        }
        else
        {
            currentActivity.BWrkId = "";
        }
    }
    else
    {
        currentActivity.BWrkId = "";
    }
}
private void SetEventNMandID()
{
    // T_SCH_WRK's WRK_NM
    currentActivity.BWrkName = eventNameCombo.Text;
    // T_SCH_TREE's WRK_NM
    currentActivity.Name = eventNameCombo.Text;
    // T_SCH_WRK's WRK_ID
    if ((eventNameCombo.SelectedIndex >= 0) && 
        (eventNameCombo.SelectedIndex < listEventID.Count))
    {
        currentActivity.BWrkId = (string)listEventID[eventNameCombo.SelectedIndex];
    }
}

Recoding using a Design Pattern

I designed two template methods: InitializeList() and InitializeItemsOnComboBox(), and two child classes: ConcreteTableToKojunComboBox and ConcreteTableToEventComboBox.

class PADUtil
{
    public abstract class AbstractTableToComboBox
    {
        public abstract void CreateList();
        public abstract bool CheckTable();
        public abstract bool HasColumnsandRows();
        public abstract void SetFilter();
        public void InitializeList()
        {
            SetFilter();
            if (CheckTable() && HasColumnsandRows())
            {
                CreateList();
            }
        }
        public abstract void SetComboBoxMember();
        public abstract int HasCurrentItem();
        public abstract void JustSetCurrentItem(int index);
        public abstract void AddandSetCurrentItem();
        public void InitializeItemsOnComboBox()
        {
            SetComboBoxMember();
            int index = HasCurrentItem();
            if (index >= 0)
            {
                JustSetCurrentItem(index);
            }
            else
            {
                AddandSetCurrentItem();
            }
        }
        public abstract object GetValueOfCurrentItem(object dispaly);
    }
    public class ConcreteTableToKojunComboBox : AbstractTableToComboBox
    {
        private DataTable table;
        private ArrayList displayList;
        private ArrayList valueList;
        private string filter = "";
        private string displayMember = "";
        private string valueMember = "";
        private EnumScheduleType scheduleType;
        private ComboBox comboBox;
        public struct CurrentItem
        {
            public object display;
            public object value;
        }
        public CurrentItem currentItem = new CurrentItem();
        public ConcreteTableToKojunComboBox(DataTable table, ArrayList displayList, 
               ArrayList valueList, DataColumn[] primaryKey, string displayMember, 
               string valueMember, EnumScheduleType scheduleType, ComboBox comboBox)
        {
            this.table = table;
            this.displayList = displayList;
            this.valueList = valueList;
            this.table.PrimaryKey = primaryKey;
            this.displayMember = displayMember;
            this.valueMember = valueMember;
            this.scheduleType = scheduleType;
            this.comboBox = comboBox;
        }
        public override bool CheckTable()
        {
            if (table == null || displayList == null || valueList == null || 
                displayMember == "" || valueMember == "")
            {
                return false;
            }
            return true;
        }
        public override bool HasColumnsandRows()
        {
            if (table.Columns.Count == 0)
            {
                table.Columns.Add(new DataColumn(displayMember));
                table.Columns.Add(new DataColumn(valueMember));
                return false;
            }
            else if (table.Rows.Count == 0)
            {
                return false;
            }
            return true;
        }
        public override void SetFilter()
        {
            if (table.Columns.Contains("SCH_TYP") && table.Columns.Contains("DEL_FLG"))
            {
                if (scheduleType == EnumScheduleType.Mschedule)
                {
                    filter = "SCH_TYP<>2";
                }
                else if (scheduleType == EnumScheduleType.Sschedule)
                {
                    filter = "SCH_TYP=2";
                }
                filter = "(" + filter + ") AND (DEL_FLG<>1)";
            }                
        }
        public override void CreateList()
        {
            foreach (System.Data.DataRow row in table.Select(filter))
            {
                displayList.Add(row[displayMember].ToString());
                valueList.Add(row[valueMember].ToString());
            }
        }
        public override void SetComboBoxMember()
        {
            this.comboBox.DisplayMember = this.displayMember;
            this.comboBox.ValueMember = this.valueMember;
        } 
        public override int HasCurrentItem()
        {
            if((currentItem.value == null))
            {
                return -1;
            }
            int index = -1;
            foreach (System.Data.DataRow row in table.Select(filter))
            {
                index++;
                if (row[valueMember].ToString() == currentItem.value.ToString())
                {
                    return index;
                }
            }
            return -1;
        }
        private DataTable MakeComboBoxDataSource()
        {
            DataTable displayTable = table.Copy();
            displayTable.Clear();
            foreach (DataRow row in table.Select(filter))
            {
                DataRow newRow = displayTable.NewRow();
                foreach (DataColumn col in table.Columns)
                {
                    newRow[col.ColumnName] = row[col.ColumnName];
                }
                displayTable.Rows.Add(newRow);
            }
            return displayTable;
        }
        public override void AddandSetCurrentItem()
        {
            DataTable displayTable = MakeComboBoxDataSource();
            System.Data.DataRow currentItemRow = displayTable.NewRow();
            currentItemRow[displayMember] = currentItem.display;
            if (currentItem.value != null)
            {
                currentItemRow[valueMember] = currentItem.value;
            }
            else
            {
                currentItemRow[valueMember] = "";
            }
            displayTable.Rows.Add(currentItemRow);
            comboBox.DataSource = displayTable;
            if (comboBox.Items.Count > 0)
            {
                comboBox.SelectedIndex = comboBox.Items.Count - 1;
            }
        }
        public override void JustSetCurrentItem(int index)
        {
            DataTable displayTable = MakeComboBoxDataSource();
            displayTable.Rows[index][displayMember] = currentItem.display;
            comboBox.DataSource = displayTable;
            if ((comboBox.Items.Count > 0) && (index >= 0) && (index < comboBox.Items.Count))
            {
                comboBox.SelectedIndex = index;
            }
        }
        public override object GetValueOfCurrentItem(object dispaly)
        {
            currentItem.display = dispaly;
            foreach (DataRow row in table.Select(filter))
            {
                if (row[displayMember] == dispaly)
                {
                    currentItem.value = row[valueMember];
                    return currentItem.value;
                }
            }
            currentItem.value = "";
            return currentItem.value;
        }
    }

    public class ConcreteTableToEventComboBox : AbstractTableToComboBox
    {
        private DataTable table;
        private ArrayList displayList;
        private ArrayList valueList;
        private string filter = "";
        private string displayMember = "";
        private string valueMember = "";
        private EnumScheduleType scheduleType;
        private ComboBox comboBox;
        public struct CurrentItem
        {
            public object display;
            public object value;
        }
        public CurrentItem currentItem = new CurrentItem();
        public ConcreteTableToEventComboBox(DataTable table, ArrayList displayList, 
               ArrayList valueList, DataColumn[] primaryKey, string displayMember, 
               string valueMember, EnumScheduleType scheduleType, ComboBox comboBox)
        {
            this.table = table;
            this.displayList = displayList;
            this.valueList = valueList;
            this.table.PrimaryKey = primaryKey;
            this.displayMember = displayMember;
            this.valueMember = valueMember;
            this.scheduleType = scheduleType;
            this.comboBox = comboBox;
        }
        public override bool CheckTable()
        {
            if (table == null || displayList == null || valueList == null || 
                displayMember == "" || valueMember == "")
            {
                return false;
            }
            return true;
        }
        public override bool HasColumnsandRows()
        {
            if (table.Columns.Count == 0)
            {
                table.Columns.Add(new DataColumn(displayMember));
                table.Columns.Add(new DataColumn(valueMember));
                return false;
            }
            else if (table.Rows.Count == 0)
            {
                return false;
            }
            return true;
        }
        public override void SetFilter()
        {
            // Need not Filter
        }
        public override void CreateList()
        {
            foreach (System.Data.DataRow row in table.Select(filter))
            {
                displayList.Add(row[displayMember].ToString());
                valueList.Add(row[valueMember].ToString());
            }
        }
        public override void SetComboBoxMember()
        {
            this.comboBox.DisplayMember = this.displayMember;
            this.comboBox.ValueMember = this.valueMember;
        }
        public override int HasCurrentItem()
        {
            if ((currentItem.value == null))
            {
                return -1;
            }
            int index = -1;
            foreach (System.Data.DataRow row in table.Select(filter))
            {
                index++;
                if (row[valueMember].ToString() == currentItem.value.ToString())
                {
                    return index;
                }
            }
            return -1;
        }
        private DataTable MakeComboBoxDataSource()
        {
            DataTable displayTable = table.Copy();
            displayTable.Clear();
            foreach (DataRow row in table.Select(filter))
            {
                DataRow newRow = displayTable.NewRow();
                foreach (DataColumn col in table.Columns)
                {
                    newRow[col.ColumnName] = row[col.ColumnName];
                }
                displayTable.Rows.Add(newRow);
            }
            return displayTable;
        }
        public override void AddandSetCurrentItem()
        {
            DataTable displayTable = MakeComboBoxDataSource();
            System.Data.DataRow currentItemRow = displayTable.NewRow();
            currentItemRow[displayMember] = currentItem.display;
            if (currentItem.value != null)
            {
                currentItemRow[valueMember] = currentItem.value;
            }
            else
            {
                currentItemRow[valueMember] = -1;
            }
            displayTable.Rows.Add(currentItemRow);
            comboBox.DataSource = displayTable;
            if (comboBox.Items.Count > 0)
            {
                comboBox.SelectedIndex = comboBox.Items.Count - 1;
            }
            // Set Items ReadOnly
            comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
        }
        public override void JustSetCurrentItem(int index)
        {
            DataTable displayTable = MakeComboBoxDataSource();
            //displayTable.Rows[index][displayMember] = currentItem.display;
            comboBox.DataSource = displayTable;
            if ((comboBox.Items.Count > 0) && (index >= 0) && (index < comboBox.Items.Count))
            {
                comboBox.SelectedIndex = index;
            }
            // Set Items ReadOnly
            comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
        }
        public override object GetValueOfCurrentItem(object dispaly)
        {
            currentItem.display = dispaly;
            foreach (DataRow row in table.Select(filter))
            {
                if (row[displayMember] == dispaly)
                {
                    currentItem.value = row[valueMember];
                    return currentItem.value;
                }
            }
            currentItem.value = "";
            return currentItem.value;
        }
    }
} 

PADUtil.AbstractTableToComboBox MStdLdtmToKojunComboBox;
PADUtil.ConcreteTableToEventComboBox MEventToEventComboBox;
/// Initialize Current Activity        
private void InitCommonVariables()
{
    // Get Selected Activity
    currentActivity = (Progress.Model.ProgressActivity)this.Activity;
    if (currentActivity.BNodeLevel == (int)ActivityNodeLevel.Kojun)
    {
        // Ready to Set ComboBox Items from M_STDLDTM DataTable
        dtMSTDLDTM = ((ProgressGanttModel)(currentActivity.GanttModel)).dtMSTDLDTM;
        listWrkID = new ArrayList();
        listWrkNM = new ArrayList();
        System.Data.DataColumn[] primaryKey = new System.Data.DataColumn[1];
        primaryKey[0] = dtMSTDLDTM.Columns[0];
        string displayMember = "WRK_NM";
        string vlaueMember = "WRK_ID";
        MStdLdtmToKojunComboBox = new PADUtil.ConcreteTableToKojunComboBox(dtMSTDLDTM, 
                                  listWrkNM, listWrkID, primaryKey, displayMember, 
                                  vlaueMember, initParams.scheduleType, kojunNameCombo);
        MStdLdtmToKojunComboBox.InitializeList();
        // Ready to Set ComboBox Items from M_EVENT DataTable
        if (currentActivity.BEventFlg == 1)
        {
            dtMEVENT = ((ProgressGanttModel)(currentActivity.GanttModel)).dtMEVENT;
            listEventID = new ArrayList();
            listEventNM = new ArrayList();
            primaryKey = new System.Data.DataColumn[1];
            primaryKey[0] = dtMEVENT.Columns[0];
            displayMember = "EVENT_NM";
            vlaueMember = "EVENT_ID";
            MEventToEventComboBox = new PADUtil.ConcreteTableToEventComboBox(dtMEVENT, 
                                    listEventNM, listEventID, primaryKey, 
                                    displayMember, vlaueMember, 
                                    initParams.scheduleType, eventNameCombo);
            MEventToEventComboBox.InitializeList();
        }
    }
}

/// Set Work Name On KojunNameComboBox
private void SetItemsonKojunNameCombo()
{
    ((PADUtil.ConcreteTableToKojunComboBox)
      MStdLdtmToKojunComboBox).currentItem.display = currentActivity.BWrkName;
    ((PADUtil.ConcreteTableToKojunComboBox)
      MStdLdtmToKojunComboBox).currentItem.value = currentActivity.BWrkId;
    MStdLdtmToKojunComboBox.InitializeItemsOnComboBox();
} 
/// Set Event Name On EventNameComboBox
private void SetItemsonEventNameCombo()
{
    ((PADUtil.ConcreteTableToEventComboBox)
       MEventToEventComboBox).currentItem.display = currentActivity.BWrkName;
    ((PADUtil.ConcreteTableToEventComboBox)
      MEventToEventComboBox).currentItem.value = currentActivity.BWrkId;
    MEventToEventComboBox.InitializeItemsOnComboBox();
}
private void SaveKojunWorkNMandID()
{
    // T_SCH_WRK's WRK_NM
    currentActivity.BWrkName = kojunNameCombo.Text;
    // T_SCH_TREE's WRK_NM
    currentActivity.Name = kojunNameCombo.Text;
    string value = (string)((PADUtil.ConcreteTableToKojunComboBox)
           MStdLdtmToKojunComboBox).GetValueOfCurrentItem(kojunNameCombo.Text);
    currentActivity.BWrkId = value;
}
private void SaveEventNMandID()
{
    // T_SCH_WRK's WRK_NM
    currentActivity.BWrkName = eventNameCombo.Text;
    // T_SCH_TREE's WRK_NM
    currentActivity.Name = eventNameCombo.Text;
    // T_SCH_WRK's WRK_ID
    string value = (string)((PADUtil.ConcreteTableToEventComboBox)
      MEventToEventComboBox).GetValueOfCurrentItem(eventNameCombo.Text);
    currentActivity.BWrkId = value;
}

I'm thinking......

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

azealer
Web Developer
Japan Japan
Ph.D(Computer Network)
Project Manger
Developer

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.140814.1 | Last Updated 30 May 2007
Article Copyright 2007 by azealer
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid