Object Oriented Design Principles

Who is Audience?

This article is intended for those who have at least a basic idea of Object oriented programming. They know the difference between classes and objects and can talk about the basic pillars of object oriented programming i.e., Encapsulation, Abstraction, Polymorphism and Inheritance.

Introduction

In the object oriented world we only see objects. Objects interact with each other. Classes, Objects, Inheritance, Polymorphism, Abstraction are common vocabulary we hear in our day-to-day careers.

In the modern software world every software developer uses object oriented language of some kind, but the question is, does he really know what object oriented programming means? Does he know that he is working as an object oriented programmer? If the answer is yes, is he really using the power of object oriented programming?

In this article we will go beyond the basic pillars of object oriented programming and talk about object oriented design.

Object Oriented Design

It’s a process of planning a software system where objects will interact with each other to solve specific problems. The saying goes, “Proper Object oriented design makes a developer’s life easy, whereas bad design makes it a disaster.”

How does anyone start?

When anyone starts creating software architecture their intentions are good. They try to use their existing experience to create an elegant and clean design.

Over time software starts to rot. With every feature request or change software design alters its shape and eventually the simplest changes to application requires a lot of effort and, more importantly, creates higher chances for more bugs.

Who is to Blame

Software solves real life business problems and since business processes keep evolving, software keeps on changing.

Changes are an integral part of the software world. Obviously because clients are paying they will demand for what they are expecting. So we cannot blame “change” for the degradation of software design. It is our design which is at fault.

One of the biggest reasons for the damaging of software design is the introduction of unplanned dependencies into the system. Every part of the system is dependant on some other part and so changing one part will affect another part. If we are able to manage those dependencies we will easily maintain the software system and software quality too.

Example

Solution – Principles, Design Patterns and Software architecture

  • Software architecture like MVC, 3-Tier, MVP tells us how overall projects are going to be structured.
  • Design pattern allows us to reuse the experience or rather, provides reusable solutions to commonly occurring problems. Example – an object creation problem, an instance management problem, etc.
  • Principles tell us, do these and you will achieve this. How you will do it is up to you. Everyone defines some principles in their lives like, “I never lie,” or, “I never drink alcohol,” etc. He/she follow these principles to make his/her life easy, but how will he/she stick to these principles is up to the individual.

In the same way, object oriented design is filled with many principles which let us manage the problems with software design.

Mr. Robert Martin (commonly known as Uncle Bob) categorized them as

  1. Class Design principles – Also called SOLID
  2. Package Cohesion Principles
  3. Package Coupling principle

In this article we will talk about SOLID principles with practical example.

SOLID

It’s an acronym of J five principles introduced by Mr. Robert Martin (commonly known as Uncle Bob) i.e., Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion. It’s said (Wikipedia) when all five principles are applied together intend to make it more likely that a programmer will create a system that is easy to maintain and extend over time. Let’s talk about every principle in detail

I) S – SRP – Single responsibility Principle

Real world comparison

I work as a team leader for one of the software firms in India. In my spare time I do some writing, newspaper editing and other various projects. Basically, I have multiple responsibilities in my life.

When something bad happens at my work place, like when my boss scolds me for some mistake, I get distracted from my other work. Basically, if one thing goes bad, everything will mess up.

Identify Problem in Programming

Before we talk about this principle I want you take a look at following class.

  • Every time insert logic changes, this class will change.
  • Every time report format changes, this class will changes.

What is the issue?

Every time one gets changed there is a chance that the other also gets changed because both are staying in the same home and both have same parent. We can’t control everything. So a single change leads to double testing (or maybe more).

What is SRP?

SRP says “Every software module should have only one reason to change”.

  • Software Module – Class, Function etc.
  • Reason to change – Responsibility

Solutions which will not Violate SRP

Now it’s up to us how we achieve this. One thing we can do is create three different classes

  1. Employee – Contains Properties (Data)
  2. EmployeeDB – Does database operations
  3. EmplyeeReport – Does report related tasks
public class Employee
{
    public string EmployeeName { get; set; }
    public int EmployeeNo { get; set; }
}
public class EmployeeDB
{
    public void Insert(Employee e) 
    {
        //Database Logic written here
    }
 public Employee Select() 
    {
        //Database Logic written here
    }
}
public class EmployeeReport
{
    public void GenerateReport(Employee e)
    {
        //Set report formatting
    }
}

Note: This principle also applies to methods. Every method should have a single responsibility.

Can a single class can have multiple methods?

The answer is YES. Now you might ask how it’s possible that

  1. A class will have single responsibility.
  2. A method will have single responsibility.
  3. A class may have more than one method.

Well the answer for this question is simple. It’s context. Here, responsibility is related to the context in which we are speaking. When we say class responsibility it will be somewhat at higher level. For instance, the EmployeeDBclass will be responsible for employee operations related to the Database whereas the EmployeeReport class will be responsible for employee operations related to reports.

When it comes to methods it will be at lower level. For instance look at following example:

//Method with multiple responsibilities – violating SRP
public void Insert(Employee e)
{     
    string StrConnectionString = "";       
    SqlConnection objCon = new SqlConnection(StrConnectionString); 
    SqlParameter[] SomeParameters=null;//Create Parameter array from values
    SqlCommand objCommand = new SqlCommand("InertQuery", objCon);
    objCommand.Parameters.AddRange(SomeParameters);
    ObjCommand.ExecuteNonQuery();
}

//Method with single responsibility – follow SRP
public void Insert(Employee e)
{            
    SqlConnection objCon = GetConnection();
    SqlParameter[] SomeParameters=GetParameters();
    SqlCommand ObjCommand = GetCommand(objCon,"InertQuery",SomeParameters);
    ObjCommand.ExecuteNonQuery();
}

private SqlCommand GetCommand(SqlConnection objCon, string InsertQuery, SqlParameter[] SomeParameters)
{
    SqlCommand objCommand = new SqlCommand(InsertQuery, objCon);
    objCommand.Parameters.AddRange(SomeParameters);
    return objCommand;
}

private SqlParameter[] GetParaeters()
{
    //Create Paramter array from values
}

private SqlConnection GetConnection()
{
    string StrConnectionString = "";
    return new SqlConnection(StrConnectionString);
}

Testing is advantageous in and of itself, but that the code has become readable is an additional advantage. The more the code is readable the simpler it seems.

II) O – OCP – Open Close Principle

Real World Comparison

Let’s assume you want to add one more floor between the first and second floor in your two floor house. Do you think it is possible? Yes it is, but is it feasible? Here are some options:

  • One thing you could have done at time you were building the house first time was make it with three floors, keeping second floor empty. Then utilize the second floor anytime you want. I don’t know how feasible that is, but it is one solution.
  • Break the current second floor and build two new floors, which is not sensible.

Identify Problem in Programming

Let’s say the Select method in the EmployeeDB class is used by two clients/screens. One is made for normal employees, one is made for managers, and the Manager Screen needs a change in the method.

If I make changes in the Select method to satisfy the new requirement, other UI will also be affected. Plus making changes in existing tested solution may result in unexpected errors.

What is OCP?

It says, “Software modules should be closed for modifications but open for extensions.” An orthogonal statement.

Solution which will not violate OCP

1) Use of inheritance

We will derive a new class called EmployeeManagerDB from EmployeeDB and override the Select method as per the new requirement.

public class EmployeeDB
{      
    public virtual Employee Select()
    {
        //Old Select Method
    }
}
public class EmployeeManagerDB : EmployeeDB
{
    public override Employee Select()
    {
        //Select method as per Manager
        //UI requirement
    }
}

Note: Now the design is considered good object oriented design if this change is anticipated at the time of the design and already has a provision within for extension (method made virtual). Now the UI code will look like:

//Normal Screen
EmployeeDB objEmpDb = new EmployeeDB();
Employee objEmp = objEmpDb.Select();

//Manager Screen
EmployeeDB objEmpDb = new EmployeeManagerDB();
Employee objEmp = objEmpDb.Select();

2) Extension method

If you are using .NET 3.5 or later then there is a second way called extension method that will let us add new methods to existing types without even touching them.

Note: There may be some more ways to achieve the desired result. As I said these are principles not commandments.

III) L – LSP – Liskov substitution principle

What is LSP?

You might be wondering why we are defining it prior to examples and problem discussions. Simply put, I thought it will be more sensible here.

It says, “Subclasses should be substitutable for base classes.” Don’t you think this statement is strange? If we can always write BaseClass b=new DerivedClass() then why would such a principle be made?

Real World Comparison

A father is a real estate business man whereas his son wants to be cricketer.A son can’t replace his father in spite of the fact that they belong to same family hierarchy.

Identify Problem in Programming

Let’s talk about a very common example.

Normally when we talk about geometric shapes, we call a rectangle a base class for square. Let’s take a look at code snippet.

public class Rectangle
{
    public int Width { get; set; }
    public int Height { get; set; }
}

public class Square:Rectangle
{
    //codes specific to
    //square will be added
}

One can say,

Rectangle o = new Rectangle();
o.Width = 5;
o.Height = 6;

Perfect but as per LSP we should be able to replace Rectangle with square. Let’s try to do so.

Rectangle o = new Square();
o.Width = 5;
o.Height = 6;

What is the matter? Square cannot have different width and height.

What it means? It means we can’t replace base with derived. Means we are violating LSP.

Why don’t we make width and height virtual in Rectangle, and override them in Square?

Code snippet

public class Square : Rectangle 
{
    public override int Width
    {
        get{return base.Width;}
        set
        {
            base.Height = value;
            base.Width = value;
        }
    }
    public override int Height
    {
        get{return base.Height;}
        set
        {
            base.Height = value;
            base.Width = value;
        }
    }        
}

We can’t because doing so we are violating LSP, as we are changing the behavior of Width and Height properties in derived class (for Rectangle height and width cannot be equal, if they are equal it’s cannot be Rectangle).

(It will not be a kind of replacement).

Solution which will not violate LSP

There should be an abstract class Shape which looks like:

public abstract class Shape
{
    public virtual int Width { get; set; }
    public virtual int Height { get; set; }
}

Now there will be two concrete classes independent of each other, one rectangle and one square, both of which will be derived from Shape.

Now the developer can say:

Shape o = new Rectangle();
o.Width = 5;
o.Height = 6;

Shape o = new Square();
o.Width = 5; //both height and width become 5
o.Height = 6; //both height and width become 6

Even after overriding in derived classes we are not changing the behavior of width and height, because when we talk about shape, there will not be any fixed rule for width and height. They may be equal, or may not be.

IV) I – ISP– Interface Segregation principle

Real World Comparison

Let’s say you purchase a new desktop PC. You will find a couple of USB ports, some serial ports, a VGA port etc. If you open the cabinet you will see lots of slots on the motherboard used for connecting various parts with each other, mostly used by hardware engineers at the time of assembly.

Those internal slots will not be visible until you open the cabinet. In short, only the required interfaces are made available/visible to you. Imagine a situation where everything was external or internal. Then there is a greater chances of hardware failure (as if life wasn’t hard enough for computer users).

Let’s say we will go to a shop to buy something (let’s say, for instance, to buy a cricket bat).

Now imagine a situation where the shopkeeper starts showing you the ball and stumps as well. It may be possible that we will get confused and may end up buying something we did not require. We may even forget why we were there in the first place.

Identify Problem in Programming

Let’s say we want to develop a Report Management System. Now, the very first task is creating a business layer which will be used by three different UIs.

  1. EmployeeUI – Show reports related to currently logged in employee
  2. ManagerUI – Show reports related to himself and the team for which he/manager belongs.
  3. AdminUI – Show reports related to individual employee ,related to team and related to company like profit report.
public interface IReportBAL
{
    void GeneratePFReport();
    void GenerateESICReport();

    void GenerateResourcePerformanceReport();
    void GenerateProjectSchedule();

    void GenerateProfitReport();
}
public class ReportBAL : IReportBAL
{    
    public void GeneratePFReport()
    {/*...............*/}

    public void GenerateESICReport()
    {/*...............*/}

    public void GenerateResourcePerformanceReport()
    {/*...............*/}

    public void GenerateProjectSchedule()
    {/*...............*/}

    public void GenerateProfitReport()
    {/*...............*/}
}
public class EmployeeUI
{
    public void DisplayUI()
    {
        IReportBAL objBal = new ReportBAL();
        objBal.GenerateESICReport();
        objBal.GeneratePFReport();
    }
}
public class ManagerUI
{
    public void DisplayUI()
    {
        IReportBAL objBal = new ReportBAL();
        objBal.GenerateESICReport();
        objBal.GeneratePFReport();
        objBal.GenerateResourcePerformanceReport ();
        objBal.GenerateProjectSchedule ();
    }
}
public class AdminUI
{
    public void DisplayUI()
    {
        IReportBAL objBal = new ReportBAL();
        objBal.GenerateESICReport();
        objBal.GeneratePFReport();
        objBal.GenerateResourcePerformanceReport();
        objBal.GenerateProjectSchedule();
        objBal.GenerateProfitReport();
    }
}

Now in each UI when the developer types “objBal” the following intellisense will be shown:

What is the problem?

The developer who is working on EmployeeUI gets access to all the other methods as well, which may unnecessarily cause him/her confusion.

What is ISP?

It states that “Clients should not be forced to implement interfaces they don’t use.” It can also be stated as “Many client specific interfaces are better than one general purpose interface.” In simple words, if your interface is fat, break it into multiple interfaces.

Update code to follow ISP

public interface IEmployeeReportBAL
{
    void GeneratePFReport();
    void GenerateESICReport();
}
public interface IManagerReportBAL : IEmployeeReportBAL
{
    void GenerateResourcePerformanceReport();
    void GenerateProjectSchedule();
}
public interface IAdminReportBAL : IManagerReportBAL
{
    void GenerateProfitReport();
}
public class ReportBAL : IAdminReportBAL 
{    
    public void GeneratePFReport()
    {/*...............*/}

    public void GenerateESICReport()
    {/*...............*/}

    public void GenerateResourcePerformanceReport()
    {/*...............*/}

    public void GenerateProjectSchedule()
    {/*...............*/}

    public void GenerateProfitReport()
    {/*...............*/}
}
public class EmployeeUI
{
    public void DisplayUI()
    {
        IEmployeeReportBAL objBal = new ReportBAL();
        objBal.GenerateESICReport();
        objBal.GeneratePFReport();
    }
}
public class ManagerUI
{
    public void DisplayUI()
    {
        IManagerReportBAL  objBal = new ReportBAL();
        objBal.GenerateESICReport();
        objBal.GeneratePFReport();
        objBal.GenerateResourcePerformanceReport ();
        objBal.GenerateProjectSchedule ();
    }
}
public class AdminUI
{
    public void DisplayUI()
    {
        IAdminReportBAL  objBal = new ReportBAL();
        objBal.GenerateESICReport();
        objBal.GeneratePFReport();
        objBal.GenerateResourcePerformanceReport();
        objBal.GenerateProjectSchedule();
        objBal.GenerateProfitReport();
    }
}

By following ISP we can make client see, what he is required to see.

V) D – DIP– Dependency Inversion principle

Real World Comparison

Let’s talk about our desktop computers. Different parts such as RAM, a hard disk, and CD-ROM (etc.) are loosely connected to the motherboard. That means that, if, in future in any part stops working it can easily be replaced with a new one. Just imagine a situation where all parts were tightly coupled to each other, which means it would not be possible to remove any part from the motherboard. Then in that case if the RAM stops working we have to buy new motherboard which is going to be very expensive.

Identify Problem in Programming

Look at the following code.

public class CustomerBAL
{
    public void Insert(Customer c)
    {
        try
        {
            //Insert logic
        }
        catch (Exception e)
        {
            FileLogger f = new FileLogger();
            f.LogError(e);
        }
    }
}

public class FileLogger
{
    public void LogError(Exception e)
    {
        //Log Error in a physical file
    }
}

In the above code CustomerBAL is directly dependent on the FileLogger class which will log exceptions in physical file. Now let’s assume tomorrow management decides to log exceptions in the Event Viewer. Now what? Change existing code. Oh no! My God, that might create a new error!

What is DIP?

It says, “High level modules should not depend upon low level modules. Rather, both should depend upon abstractions.”

Solution with DIP

public interface ILogger
{
    void LogError(Exception e);
}

public class FileLogger:ILogger
{
    public void LogError(Exception e)
    {
        //Log Error in a physical file
    }
}
public class EventViewerLogger : ILogger
{
    public void LogError(Exception e)
    {
        //Log Error in a physical file
    }
}
public class CustomerBAL
{
    private ILogger _objLogger;
    public CustomerBAL(ILogger objLogger)
    {
        _objLogger = objLogger;
    }

    public void Insert(Customer c)
    {
        try
        {
            //Insert logic
        }
        catch (Exception e)
        {            
            _objLogger.LogError(e);
        }
    }
}

As you can see the client depends on abtraction i.e, ILogger which can be set to an instance of any derived class.

So now we’ve covered all five principles of SOLID. Thanks Uncle Bob.

Is it end?

Now the question is, are there more principles other than those categorized by Uncle Bob? The answer is yes, but we will not going to describe each and every thing in detail for now. But they are:

  • Program to Interface Not Implementation.
  • Don’t Repeat Yourself.
  • Encapsulate What Varies.
  • Depend on Abstractions, Not Concrete classes.
  • Least Knowledge Principle.
  • Favor Composition over Inheritance.
  • Hollywood Principle.
  • Apply Design Pattern wherever possible.
  • Strive for Loosely Coupled System.
  • Keep it Simple and Sweet / Stupid.

Conclusion

We can’t avoid changes. The only thing we can do is develop and design software in such a way that it is able to handle such changes.

  • SRP should be kept in mind while creating any class, method or any other module (which even applies to SQL stored procedures and functions). It makes code more readable, robust, and testable.
  • As per my experience we can’t follow DIP each and every time, sometimes we have to depend on concrete classes. The only thing we have to do is understand the system, requirements and environment properly and find areas where DIP should be followed.
  • Following DIP and SRP will opens a door to implement OCP as well.
  • Make sure to create specific interfaces so that complexities and confusions will be kept away from end developers, and thus, the ISP will not get violated.
  • While using inheritance take care of LSP.

Hope all of you enjoyed reading this article. Thank you for the patience.

LINK gốc: http://www.codeproject.com/Articles/567768/Object-Oriented-Design-Principles

From No Factory to Factory Method

Introduction

When we hear the word Design Pattern, the first question that comes to our mind is, “What are Design Patterns?”
Design Patterns are reusable and documented solutions for recurring problems in software development.
Gang of four (GOF) have categorized Design Patterns into 3 categories

  • Creational
  • Structural
  • Behavioral

When I started to learn Design Pattern I found Factory method as a very intriguing pattern. It is one of the most controversial and confused Creational Pattern. There is a alot of confusion in People to understanding this pattern .
First of all let me make all of you clear there is nothing like Factory Pattern (as per GOF design pattern list), GOF has something called Factory Method Pattern. (We will come across with both the terminology later in this stage)

In this article for discussion and explanation purpose I am introducing to you, two fictional characters Alexander (a .NET developer) and Thomas (CEO of an IT institute called Programmer24X7).

Story begins on the day when Thomas contacts Alexander and asks him to take up role of architect in his in-house project called “Course Management System”. We will see how Alexander progresses his knowledge about Factory Method Pattern day by day and how finally he come up with a great solution.

Before you starts reading this article, a small advice from my side, keep some snacks ready besides you, because it’s going to be a weary 6 day story. Basically I am trying to play with your patience. Smile | <img src= don’t worry just kidding. It’s gonna be fun, you will enjoy reading this article and towards the end of this article you can proudly say “I know Factory Method Pattern”.

So relax and let’s start our journey to learn Factory Method Pattern

Index

Day 1

Alexander (our .NET developer) collects requirements from Thomas (our Programmer24X7 CEO). One of his primary requirements was to build a module which will manage online courses offered in the Programmer24X7 (technical institute).

How Alexander started?

I) The system Alexander is going to develop is Course Management System, so the first logical step was to start creating Course Library.

II) Next step will be creating instance of courses and building the UI – User Interface. Following is the most obvious code every programmer thinks about and even Alexander did the same.

Approach 1 – Without Factory Approach

AbstractCourse objCourse = null;
switch(StrUserInput)
{
    case "N":
    objCourse = new NetCourse();
    break;
    case "J":
    objCourse = new JavaCourse();
    break;
}
objCourse.CreateCourseMaterial();
objCourse.CreateSchedule();
//Display objCourse.CourseName and objCourse.CourseDuration

Final step – demonstration

Since module was ready, Alexander demonstrated the same to Thomas, and Thomas felt great about the architecture. Alexander’s efforts were well appreciated but, it all didn’t end there. He then took the requirement to next logical level where he shared his further plan with regards to the application. He said,

  • He is planning to add new online courses like C++, VC++ etc. and would like to stop few courses in future.
  • In future In Programmer24X7 offline courses are going to be conducted, so make sure to make everything reusable.

Thomas requested Alexander to make changes as per this advance scope. Well it came to Alexander as a Big Surprise

It was like out of the frying pan but into the fire situation for Alexander.

“Adding a new course means”, open the existing UI Code existing logic (add some more switch cases and in future remove some existing case.)

Consider a situation of builder, who is asked to add one more floor between 1st and 2nd floor after the building construction is over taking care that building doesn’t collapse.

Problem with the Approach 1

  • SOLID principle OCP (Open Closed Principle) will be violated when Course library modifies. (OCP says, software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification)
  • Reusing the same (Course creation) logic in another UI is not possible.

What Alexander learnt?

Alexander realized an important thing about software development and learnt a great lesson “Changes are integral part of development and system should developed in such a way that it can be easily adapted to such changes without modifying existing tested sections.”

Isn’t it funny, change the system but don’t change the code. Well let’s see how we can do that.

Move to Index

Day 2

How Alexander Proceeded?

Alexander woke up early morning next day. Coffee was in his hand but mind was still thinking about the problem in hand. It was very difficult for him to find the right star from dark sky but finally he managed to find the Moon and there came Approach 2.

  • Sky – My Brain
  • Stars – Thoughts
  • Moon – Solution for Course Library problem

 

Approach 2 – Simple Factory Approach

 

In the first approach UI was creating Course Objects.

Now how it will be if the power of object creation is taken away from UI and give it to someone else. Here someone else is called Simple Factory class.

What is Simple Factory?

Simple Factory is a class with a public static method which will actually do the object creation task according to the input it gets.

public class CourseFactory
{
    public static AbstractCourse CreateCourse(string ScheduleType)
    {
        AbstractCourse objCourse = null;
        switch(ScheduleType)
        {
            case "N":
            objCourse = new NetCourse();
            break;
            case "J":
            objCourse = new JavaCourse();
            break;
            //Add more case conditions here for VC++ and C++
        }
        objCourse.CreateCourseMaterial();
        objCourse.CreateSchedule();
        return objCourse;
    }
}

UI

AbstractCourse objCourse = CourseFactory.CreateCourse(StrUserInput);    
//Display objCourse.CourseName and objCourse.CourseDuration

Advantages of the Approach 2

  • Whenever new course will be introduced, the one which gets changed is factory not client code.
  • As Factory is class any one can use it who have access. In short Course logic now can be reused.

Final step – demonstration

Later in the evening Alexander reached Programmer24X7 office to demonstrate this revised architecture. But before Alexander started to express his anxiety, there came another surprising request. Thomas said, “I think, it’s better if we add one more UI for corporate schedule as well. Reason is that, Now-a-days my corporate training count has increased a lot, so it’s becoming impossible for me to manage.”

I) Now the very first thing we should do is, changing course library (because we need to add corporate courses as well).

II) Add some more case conditions to our Simple Factory class.

public class CourseFactory
{
    public static AbstractCourse CreateCourse(string ScheduleType)
    {
        AbstractCourse objCourse = null;
        switch(ScheduleType)
        {
            case "CN":
            objCourse = new CNetCourse();
            break;
            case "CJ":
            objCourse = new CJavaCourse();
            break; 
            case "CB":
            objCourse = new CBICourse();
            break; 
            case "OJ":
            objCourse = new OJavaCourse();
            break;
            case "ON":
            objCourse = new ONetCourse();
            break;
        }
        objCourse.CreateCourseMaterial();
        objCourse.CreateSchedule();
        return objCourse;
    }
}

Problem with the Approach 2

New requirements are easily covered using Simple Factory Approach, then what’s the matter?

  • All though all classes are derived from Abstract Course, adding five case conditions in a single Simple Factory violates SOLID Principle SRP – Single Responsibility Principle. (SRP says a class should have only one reason to change.)
    And here Factory class will be changed

    • Whenever new corporate course introduces or modified.
    • Whenever new online course introduces or modified.

So this Simple Factory solution will not workout in current problem context.

Move to Index

Day 3

Let’s list down all our requirements.

  • We need Factory for online Courses
  • We need Factory for corporate Courses
  • We don’t want to create single Factory for both modules.

 

 

  • How if use Multiple Simple Factories.
    1. OnlineCourseFactory
    2. CorporateCourseFactory

 

Approach 3 – Multiple Simple Factory Approach

 

In this approach we will have multiple simple factories each having a static method which will create an instance based on input it gets.

public class CorporateCourseFactory
{
    public static AbstractCourse CreateCourse(string ScheduleType)
    {
        AbstractCourse objCourse = null;
        switch(ScheduleType)
        {
            case "N":
            objCourse = new CNetCourse();
            break;
            case "J":
            objCourse = new CJavaCourse();
            break;
            case "B":
            objCourse = new CBICourse();
            break;
        }
        objCourse.CreateCourseMaterial();
        objCourse.CreateSchedule();
        return objCourse;
    }
}
public class OnlineCourseFactory
{
    public static AbstractCourse CreateCourse(string ScheduleType)
    {
        AbstractCourse objCourse = null;
        switch(ScheduleType)
        {
            case "N":
            objCourse = new ONetCourse();
            break;
            case "J":
            objCourse = new OJavaCourse();
            break;
        }
        objCourse.CreateCourseMaterial();
        objCourse.CreateSchedule();
        return objCourse;
    }
}

Online Course UI

AbstractCourse objCourse = OnlineCourseFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration

Corporate Course UI

AbstractCourse objCourse = CorporateCourseFactory.CreateCourse(StrUserInput);    
//Display objCourse.CourseName and objCourse.CourseDuration

Everything settled problem solved.

Move to Index

Day 4

Next day Alexander reached Programmer24X7 and explained the architecture to Thomas What is Thomas’s reply? Good or Bad?

Small transcript of the big discussion we had after looking into the architecture.

Thomas: Sorry Alexander but I don’t think this solution will work.

Alexander: Why Sir?

Thomas: See, it’s great that there exist a separate Factory for every Course group. (OnlineCourseFactory, CoporateCourseFactory).
But how will you keep a control over each and every factory. I meant how you will make sure that every factory is creating objects properly, for instance how will you be sure that each factory is following a company standard and creates course materials and schedule prior to returning the object.
It may possible that in future one more kind of factory say OfflineCourseFactory is added for managing offline courses and unknowingly it just violates the company standard and creates course materials in his own way.

Alexander: You are right Sir. Let me think about a full proof and final solution, Give me a day.

Thomas: No problem Alexander. Have a nice day.

Problem with the Approach 3

  • Every factory is independent here. There is no strict rule for defining factories. In this approach each factory can have their own structure and standards.

Move to Index

Day 4 – Night

Let’s list down all our requirements.

  • We need Factory for online Courses
  • We need Factory for corporate Courses
  • We don’t want to create single Factory for both modules.
  • There should be some rule how to define factories, which everybody should follow.

 

 

  • How it would be if we use combination of approach 3 (that is whenever required create new factory)
    plus Inheritance or Composition.

 

 

  • Time to sleep.

Move to Index

Day 5

What Alexander was talking about last night?

  • Put all common functionalities in a single place (class) and reuse them in all factories.
    We call it “ReusbaleClass” for discussion purpose. We need reusability –
    we can do it by 2 ways.

    • With inheritance – Derive all Factories from ReusbaleClass –> Call it Solution 1
    • With composition – All factories will have a member of type ReusbaleClass –> Call it Solution 2
  • Let factories override some functionality (which is different for every factory) defined in ReusbaleClass.
    • We need to override means Solution 1 will fit perfect.

Approach 4 – Factory Method Approach

In short we need a class here which will do all the common tasks and expose a virtual or abstract function.

So let’s create AbstractCourseFactory which will encapsulate common functionalities with an additional overridable (virtual or abstract) method and then recreate our OnlineCourseFactory and CorporateCourseFactory.

public abstract class AbstractCourseFactory
{
    public AbstractCourse CreateCourse(string ScheduleType)
    {
        AbstractCourse objCourse = this.GetCourse(ScheduleType);        
        objCourse.CreateCourseMaterial();
        objCourse.CreateSchedule();
        return objCourse;
    }
    public abstract AbstractCourse GetCourse(string ScheduleType);
}

Please note GetCourse method is abstract

Now everyone (every factory) will easily override this GetCourse method.

public class CorporateCourseFactory:AbstractCourseFactory
{
    public override AbstractCourse GetCourse(string ScheduleType)
    {
        switch(ScheduleType)
        {
            case "N":
            return new CNetCourse();            
            case "J":
            return new CJavaCourse();
            default:
            return null;
        }
    }
}
public class OnlineCourseFactory : AbstractCourseFactory
{
    public override AbstractCourse GetCourse(string ScheduleType)
    {
        switch(ScheduleType)
        {
            case "N":
            return new ONetCourse();
            case "J":
            return new OJavaCourse();
            default:
            return null;
        }
    }
}

How Gang of Four defined Factory Method Pattern

“This pattern defines an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses”.
Definition is self-explanatory now.

Move to Index

Day 6

Time to show the final demo to Thomas.

Now final UI code will look like

Online Course UI

AbstractCourseFactory objFactory = new OnlineCourseFactory();
AbstractCourse objCourse = objFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration

Corporate Course UI

AbstractCourseFactory objFactory = new CorporateCourseFactory();
AbstractCourse objCourse = objFactory.CreateCourse(StrUserInput);
//Display objCourse.CourseName and objCourse.CourseDuration

Advantages with the Approach 4

  • If in the future a new course group (say for instance offline course) introduced in Programmer24X7, a new factory will be derived from AbstractCourse, encapsulating creation of all concrete courses (say for instance Offline Java Courses, Offline .NET Course) related to that group. It’s that simple.

That’s all about the Factory Method patterns. Finally Thomas seems happy because all his requirements seem satisfied and Alexander is also happy because now he has become champ in Factory Method Pattern.

Move to Index

Additional approaches and thoughts

  • Is parent factory has to be abstract always?
    Answer for this question is No. We can make it non abstract if required and add default implementation to GetCourse method making it virtual.
  • Is switch is must in factories?
    No. We can replace switch loop with the Dictionary in .NET.
  • Is inheritance from second level factory is possible?
    Yes absolutely and that’s how factory method works. Initially we had AbstractCourseFactory with its default implementation for GetCourse method, which will be later extended by OnlineCourseFactory adding its own implementation for GetCourse method, which in turn can be a virtual method. So that later say when a new OnlineAdvanceCourse is introduced in Programmer24X7 existing, OnlineCourseFactory can easily be extended.
  • What will be the advantage of using MultiLevel inheritance in case of Factory Method Pattern?
    Well, consider following scenario.

    • We have our AbstractCourseFactory and OnlineCourseFactory.
    • OnlineCourseFactory override GetCourse method for defining online courses that is Java and .net.
    • Now let’s assume new courses are added after some year to Online Course and we are not even interested in opening OnlineCourseFactory.
    • OnlineCourseFactoryVersion2 will be introduced now.
    • Now if we derive OnlineAdvanceCourseFactory from AbstractCourseFactory we are supposed to define all previous courses like Java and .NET along with new one resulting redundant code.
    • Other than that what we can do is we will take help of Dictionaries for storing all available courses, and goes adding courses to it on each level.

Let’s look at the code snippet for same.

public abstract class AbstractCourseFactory
{
    protected Dictionary<string, AbstractCourse> ObjCourses;
    public AbstractCourseFactory()
    {
        ObjCourses = new Dictionary<string, AbstractCourse>();
    }
}
public class OnlineCourseFactoryVersion2 : OnlineCourseFactory
{
    public OnlineCourseFactoryVersion2()
    {
        ObjCourses.Add("V", new OVCourse());
    }    
}

Note: So using Dictionaries in Factory Method Pattern is always considered as a good approach.

So this completes my first article on Factory Pattern… Hope you liked it… Please don’t forget to leave your comments below…. Your positive and negative comments will encourage me to write better… Thank you!!! Smile | <img src=

 

LINK: http://www.codeproject.com/Articles/492900/From-No-Factory-to-Factory-Method

Windows Service State Publisher

Introduction

ServiceStatePublisher extends the .NET System.ServiceProcess library. The ServiceStatePublisherlibrary introduces the ability to observe or listen for state changes to a Windows Service.

Why create this library extension? To get experience using several design patterns. In particular, this project will incorporate 3 design patterns:

  1. Singleton
  2. State
  3. Observer/Publish-Subscribe

Having been a casual observer of this site for awhile, I know the design patterns topic is one of those religious hotbeds. For me, they represent a nice way to communicate what you’re doing — and if by chance someone recognizes the design pattern…you know, “hey, that’s the fuzzy duck pattern“…then all the better. I don’t take it as criticism or superiority, but rather as a compliment. The observer was excited to recognize something they learned can be used in practice. And, the code was clear enough for them to see the forest through the trees (i.e. beneath the surface of the code). Hopefully, this code will be clear enough. Wink | ;-)

To demonstrate the use of this library, I have constructed the Oracle Service Manager application, found elsewhere on this site. Oracle Service Manager mimics the Microsoft SQL Server Service Manager.

Background

I have listed the references, at the end of this article, from which I derived my work; however, there are many articles on this site, and the Internet, that are excellent sources for the topics covered. Topics covered include the designpatterns identified above as well as .NET Framework topics such as the System.ServiceProcess .NET namespace, delegates, and events.

Problem Analysis

Windows Services are not designed to fire events alerting observers when a service has changed state. This library extension provides a framework to add one or more service observers. For example, if you wanted to create a utility to monitor and control the Oracle Windows services – just like the SQL Server Service Manager – you would need 3 observers: a dialog observer, a tray icon observer, and a timer/polling observer. A change in the state of the server ought to be broadcasted to all listeners, so they can decide if there is any action to take – like updating a user interface.

I have created a project and wrote an article, found elsewhere on CodeProject, for just this purpose – monitoring and controlling Oracle services – it’s called Oracle Service Manager.

Using Design Patterns

There are two primary issues to solve. The first is the state of the service. The operations performed on a service (e.g. Start, Stop, Pause, and Continue) are dependent on the internal state of the service. In other words, a running service can be stopped and, possibly, paused; however it cannot be started or continued. Most of the time, this issue is solved with a big conditional statement. The State pattern puts each branch of the conditional statement in a separate class. [GHJV98]

The second issue concerns notifying interested parties of the change in state. When a running service stops, all parties interested in observing the service should be notified of the new state regardless of whether that party initiated the request. The Observer pattern allows us to notify other objects without making assumptions about who these objects are. In other words, you don’t want these objects tightly coupled. [GHJV98]

Gamma et al, classify both patterns as behavioral. In addition, the two patterns have a relationship to one another in this library. That is, examining the two patterns reveals, the observer pattern means nothing unless the state of a service changes. This implies that the observer pattern has a dependency on the state pattern. Therefore, the observer pattern implementation needs to subclass the state pattern implementation. In short, the observer subject will derive from, or extend, the state context class.

The state pattern declares each state be represented by a concrete class. This introduces a decision of when to allocate and clean up the concrete state objects. Since we are only interested in tracking one service at a time, and we have a limited number of concrete states, we can minimize memory allocations by creating all concrete state objects at startup. This introduces a requirement to ensure and manage a single instance. This problem is solved by a thirdpattern – the Singleton pattern [GHJV98].

Below, I discuss the characteristics of the design pattern implementations. If you are only interested in using this library, your interest will lie in one of two classes: the ServiceContext in the State pattern; or the ServiceSubjectin the Observer pattern.

State Pattern

Figure 1.  Diagram of State Pattern as illustrated in Design Patterns [GHJV98]

The State pattern diagrammed above outlines the participants needed to support the model. The equivalent types needed for the ServiceStatePublisher library are:

Context  ServiceContext.

  • Defines the interface of interest to clients. In other words, as a user of this pattern, this is the class to program against. This class exposes all supported behaviors and properties encapsulated by the ConcreteState classes.
  • Maintains an instance of a ConcreteState subclass that defines the current state
  • Context delegates state-specific requests to the current ConcreteState object†
  • Context passes itself as an argument to the State object handling the request. This lets the State object access the context†
  • Either Context or the ConcreteState subclasses can decide which state succeeds another and under what circumstances†
public class ServiceContext
{
    protected ServiceController _controller;
    protected ServiceState _state;

    public ServiceContext()
    {
        State = ServiceStateUnknown.Instance;
        Controller = null;
    }

    public void Start()
    {
        State.Start( this);
    }

    public void Stop()
    {
        State.Stop( this);
    }

    public void Pause()
    {
        State.Pause( this);
    }

    public void Continue()
    {
        State.Continue( this);
    }
}

State  ServiceState.

  • Defines an interface for encapsulating the behavior associated with a particular state of the Context
  • I did not implement this as an interface because the actual implementation has some important, but not obvious, default behavior. So, instead, I used a public abstract class to indicate this is a base class from which subclasses derive. More importantly, this class cannot be instantiated on its own. Indeed, this class is the base class for the ConcreteState classes discussed below.
  • As a base class, ServiceState is the natural place to put common error logging for each of the subclasses.
  • The important default behavior is the empty body for each virtual function. This means, by default, a call to a method that is not overridden will do nothing. This will ease the burden for each ConcreteState class.
public abstract class ServiceState
{
    public virtual void Start( ServiceContext context) { }
    public virtual void Start( ServiceContext context, string[] args) { }
    public virtual void Stop( ServiceContext context) { }
    public virtual void Pause( ServiceContext context) { }
    public virtual void Continue( ServiceContext context) { }

    …

    protected virtual void LogError( string message, EventLogEntryType entryType)
    {
        if (!EventLog.SourceExists( SSP_SOURCE))
            EventLog.CreateEventSource( SSP_SOURCE, SSP_EVENTLOG);

        EventLog sspLog = new EventLog();
        sspLog.Source = SSP_SOURCE;

        sspLog.WriteEntry( message, entryType);

        sspLog.Close();
    }
}
ConcreteStates ServiceRunningServiceStoppedServicePaused,
ServicePendingStartServicePendingStopServicePendingPause,
ServicePendingContinueServiceStateUnknown
  • Each subclass implements a behavior associated with a state of the Context
  • Each ConcreteState class is derived from ServiceState.
  • Each ConreteState has a one-to-one mapping with the ServiceControllerStatuses in .NET, with one exception.
  • Included is a class to reflect an unknown state, such as when a server or service has not been selected.
  • Because the base class, ServiceState, implements a default behavior, only those methods requiring overrides must be implemented. In other words, the ServiceRunning state need only override the methods that are allowable in that state – Stop() and Pause(). If the client program calls Start() or Continue() when thestate is ServiceRunning, the default behavior is executed – do nothing. This treatment means we do not need to explicitly check for invalid requests, because the invalid request will be dealt with gracefully without error.
public class ServiceRunning : ServiceState
{
    …

    public override void Stop( ServiceContext context)
    {
        try
        {
            context.Controller.Stop();
            context.Controller.WaitForStatus( 
                ServiceControllerStatus.Stopped, new TimeSpan(0,0,30));
            ChangeState( context, ServiceStopped.Instance);
        }
        catch (TimeoutException te)
        {
            LogError( te.Message, EventLogEntryType.Warning);
            throw;
        }
    }

    public override void Pause( ServiceContext context)
    {
        try
            {
            context.Controller.Pause();
            context.Controller.WaitForStatus( 
                ServiceControllerStatus.Paused, new TimeSpan(0,0,30));
            ChangeState( context, ServicePaused.Instance);
        }
        catch (TimeoutException te)
        {
            LogError( te.Message, EventLogEntryType.Warning);
            throw;
        }
    }
}

Observer Pattern

Figure 2.  Diagram of Observer Pattern as illustrated in Design Patterns [GHJV98]

The Observer pattern diagrammed above outlines the participants needed to support the model. The Observerpattern is also known as: Listener and Publish-and-Subscribe. One noteworthy item is how well .NET provides native support for this pattern through built-in functionality found in delegates and events. The equivalent types needed for the ServiceStatePublisher library are:

Subject  Not applicable.

  • Knows its observers. Any number of Observer objects may observe a subject
  • Provides an interface for attaching and detaching Observer objects§ (e.g., in C#, the syntax to attach isobject.event += new EventHandler(); to detach, C# uses the -= operator)
  • .NET provides this functionality through its built-in support of delegates and events
  • The ConcreteSubject establishes this contract through .NET’s event support – see below.

ConcreteSubject ServiceSubject.

  • This is the publisher and defines the interface of interest to clients’. In other words, if you want published events, this is the class you should use, or program against, in your application.
  • Stores state of interest to ConcreteObserver objects§
  • Sends a notification to its observers when its state changes§ (i.e., publishes the event to subscribers)
  • .NET supports this functionality through its built-in support of delegates and events
public class ServiceSubject : ServiceContext
{
    public event EventHandler ServerChanged;
    public event EventHandler ServiceChanged;
    public event EventHandler StateChanged;

    protected string _serverName;

    public ServiceSubject() : base() { }

    public ServiceSubject( ServiceController service)
    {
        Controller = service;
    }

    public virtual string ServerName
    {
        get { return _serverName; }
        set
        {
            _serverName = value;
            OnServerChanged( EventArgs.Empty);
            if (Controller != null && _serverName != Controller.MachineName)
                Controller = null;
        }
    }

    public override ServiceController Controller
    {
        get { return _controller; }
        set
        {
            _controller = value;
            _state = QueryServiceState();
            OnServiceChanged( EventArgs.Empty);
        }
    }

    public override ServiceState State
    {
        get { return _state; }
        set
        {
            _state = value;
            OnStateChanged( EventArgs.Empty);
        }
    }

    public virtual void RefreshServices()
    {
        OnServerChanged( EventArgs.Empty);
    }

    protected virtual void OnServerChanged( System.EventArgs e)
    {
        if (ServerChanged != null)
            ServerChanged( this, e);
    }

    protected virtual void OnServiceChanged( System.EventArgs e)
    {
        if (ServiceChanged != null)
            ServiceChanged( this, e);
    }

    protected virtual void OnStateChanged( System.EventArgs e)
    {
        if (StateChanged != null)
            StateChanged( this, e);
    }
}

Observer Not applicable.

  • Defines an updating interface for objects that should be notified of changes in a subject§
  • .NET provides this functionality through its built-in support of delegates and events

ConcreteObservers Implemented in client application.

  • This is the actual subscriber or listener
  • Maintains a reference to a ConcreteSubject object§
  • Stores state that should stay consistent with the subject’s§
  • Implements the Observer updating interface to keep its state consistent with the subject’s§
  • .NET provides this functionality through its built-in support of delegates and events
  • The observers are implemented in the client application. I created an example, Oracle Service Manager, for some “real” world applicability.
using System;
using System.ServiceProcess;
using kae.ServiceStatePublisher;

public class SampleObserver
{
    public SampleObserver( ServiceSubject subject)
    {
        if (subject != null)
        {
            subject.ServerChanged += new EventHandler( this.OnServerChanged);
            subject.ServiceChanged += new EventHandler( this.OnServiceChanged);
            subject.StateChanged += new EventHandler( this.OnStateChanged);
        }
    }

    private void OnServerChanged( object sender, EventArgs e)
    {
        ServiceSubject subject = (ServiceSubject) sender;
        …
    }

    private void OnServiceChanged( object sender, EventArgs e)
    {
        ServiceSubject subject = (ServiceSubject) sender;
        …
    }

    private void OnStateChanged( object sender, EventArgs e)
    {
        ServiceSubject subject = (ServiceSubject) sender;
        …
    }
}

Singleton Pattern

Figure 3.  Diagram of Singleton Pattern as illustrated in Design Patterns [GHJV98]

The Singleton pattern diagrammed above outlines the sole participant needed to support the model. The Singletonpattern is applied differently depending on whether you need a single instance inside a single process or across multiple processes. In the latter case, an operating system level resource must be used. In the former case, a static constructor can be used to create the one and only instance.

Singleton ServiceRunningServiceStoppedServicePaused
ServicePendingStartServicePendingStopServicePendingPause
ServicePendingContinueServiceStateUnknown
  • Defines an Instance operation that lets clients access its unique instance. Instance is a class operation**
  • Responsible for creating its own unique instance**
  • In C#, we use a static property as the accessor
public class ServiceRunning : ServiceState
{
    private static ServiceRunning _instance;

    static ServiceRunning()
    {
        lock (typeof(ServiceRunning))
        {
            if (_instance == null)
                _instance = new ServiceRunning();
        }
    }

    public static ServiceRunning Instance
    {
        get { return _instance; }
    }

    …
}

Future Directions

As I have mentioned above, the ServiceStatePublisher library is used in a companion article, Oracle Service Manager, as an example application that may have some relevance to your development environment. In addition, using this library for a Visual Studio add-in to manage the Windows Services of any database (e.g., Oracle, DB2, MySQL, SQL Server, etc.) could be a nice alternative to the browsing mechanism offered by the Server Explorer in Visual Studio. Perhaps, there is also an enhancement to ensure changes in state happen in a worker thread, allowing the main thread to be more responsive to the interface.

LINK: http://www.codeproject.com/Articles/7043/Windows-Service-State-Publisher

Understanding and Implementing State Pattern in C#

There are times when we find some scenarios in our application when we need to maintain the state of a sub system. This state needs to be changed based on some conditions and/or user actions. One way to keep track of such states is by using the conditional logic in code.

Using conditional logic will get us the desired result but that would result in a code that is less understandable and is harder to maintain. Also, if we need to add more states in the system then that is very difficult and could create problems in existing system too.

To tackle such problems efficiently, GoF suggest use of State pattern. GoF defines state pattern as “Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

It can also be thought of as an object oriented state machine. Let us see the major classes in this pattern.

  • Context: This is the actual object who is accessed by the client. The state of this object needs to be tracked.
  • State: This is an interface or abstract class that defines the common behavior associated with all the possiblestates of the Context.
  • ConcreteState: This class represent a state of the Context. Each state will be represented as one concrete class.

Using the code

Let us try to implement a small example to understand the state pattern in detail. Let us try to implement the software for a dummy ATM machine. The ATM machine is with us and the Bank has decided to have 3 states for this machine.

  1. No card in the machine
  2. Card inserted and has been validated
  3. Cash withdrawn

Now first let us see how we would implement this solution without using the state pattern. We would create a class for the ATM and then have the state of the ATM maintained locally. Following code snippet shows how we could implement such ATM class and keep the state of the machine inside the object itself.

class NoStateATM
{
    public enum MACHINE_STATE
    {
        NO_CARD,
        CARD_VALIDATED,        
        CASH_WITHDRAWN,
    }

    private MACHINE_STATE currentState = MACHINE_STATE.NO_CARD;
    private int dummyCashPresent = 1000;

    public string GetNextScreen()
    {
        switch (currentState)
        {
            case MACHINE_STATE.NO_CARD:
                // Here we will get the pin validated
                return GetPinValidated();
                break;
            case MACHINE_STATE.CARD_VALIDATED:
                // Lets try to withdraw the money
                return WithdrawMoney();
                break;
            case MACHINE_STATE.CASH_WITHDRAWN:
                // Lets let the user go now
                return SayGoodBye();
                break;            
        }
        return string.Empty;
    }

    private string GetPinValidated()
    {
        Console.WriteLine("Please Enter your Pin");
        string userInput = Console.ReadLine();

        // lets check with the dummy pin
        if (userInput.Trim() == "1234")
        {
            currentState = MACHINE_STATE.CARD_VALIDATED;
            return "Enter the Amount to Withdraw";
        }
            
        // Show only message and no change in state
        return "Invalid PIN";
    }

    private string WithdrawMoney()
    {            
        string userInput = Console.ReadLine();

        int requestAmount;
        bool result = Int32.TryParse(userInput, out requestAmount);

        if (result == true)
        {
            if (dummyCashPresent < requestAmount)
            {
                // Show only message and no change in state
                return "Amount not present";
            }

            dummyCashPresent -= requestAmount;
            currentState = MACHINE_STATE.CASH_WITHDRAWN;

            return string.Format(@"Amount of {0} has been withdrawn. Press Enter to proceed", requestAmount);
        }

        // Show only message and no change in state
        return "Invalid Amount";
    }

    private string SayGoodBye()
    {
        currentState = MACHINE_STATE.NO_CARD;
        return string.Format("Thanks you for using us, Amount left in ATM: {0}", dummyCashPresent.ToString());
    }
}

Now when we run the class we can see that this works perfectly from the functionality perspective.

The problem will come when we need to add more states. Whenever we need to add more states to this ATM machine we need to open up the ATM machine code and then add more logic inside this class itself which is a clear violoation of Open-Close priciple. Also since we have all that state managed in form of conditional logic, there are some possibilities that changing code to add new states will break existing functionality too i.e. this way is more error prone.

So, what would be the better way to do this? The better way to do this is by implementing the same solution usingstate pattern. The only thing that we need to do is “encapsulate what varies”. So we will go ahead and pull the staterelated logic from the ATM class and create seprate classes for each state.

Let us start by modifying the ATM class so that it will contain no state related information. It will only keep an handle to the object which keeps track of its state.

public class ATM
{
    public ATMState currentState = null;        

    public ATM()
    {
        currentState = new NoCardState(1000, this);
    }

    public void StartTheATM()
    {
        while (true)
        {
            Console.WriteLine(currentState.GetNextScreen());
        }
    }
}

Now the member variable in this class that is being used as the handle to the state is just an abstract class. This class will point to the actual concrete implementation of state i.e. the real state of the machine dynamically.

public abstract class ATMState
{
    private ATM atm;

    public ATM Atm
    {
        get { return atm; }
        set { atm = value; }
    }
    private int dummyCashPresent = 1000;

    public int DummyCashPresent
    {
        get { return dummyCashPresent; }
        set { dummyCashPresent = value; }
    }

    public abstract string GetNextScreen();
}

And finally we have all the concrete classes, each for one state of the ATM machine. Lets look at all the state classes now

The class for NO_CARD state:

class NoCardState : ATMState
{
    // This constructor will create new state taking values from old state
    public NoCardState(ATMState state)     
        :this(state.DummyCashPresent, state.Atm)
    {
        
    }

    // this constructor will be used by the other one
    public NoCardState(int amountRemaining, ATM atmBeingUsed)
    {
        this.Atm = atmBeingUsed;
        this.DummyCashPresent = amountRemaining;
    }

    public override string GetNextScreen()
    {            
        Console.WriteLine("Please Enter your Pin");
        string userInput = Console.ReadLine();

        // lets check with the dummy pin
        if (userInput.Trim() == "1234")
        {
            UpdateState();
            return "Enter the Amount to Withdraw";
        }

        // Show only message and no change in state
        return "Invalid PIN";
    }

    private void UpdateState()
    {
        Atm.currentState = new CardValidatedState(this);
    }
}

The class for CARD_VALIDATED state:

class CardValidatedState : ATMState
{
    // This constructor will create new state taking values from old state
    public CardValidatedState(ATMState state)    
        :this(state.DummyCashPresent, state.Atm)
    {
        
    }

    // this constructor will be used by the other one
    public CardValidatedState(int amountRemaining, ATM atmBeingUsed)
    {
        this.Atm = atmBeingUsed;
        this.DummyCashPresent = amountRemaining;
    }

    public override string GetNextScreen()
    {
        string userInput = Console.ReadLine();

        int requestAmount;
        bool result = Int32.TryParse(userInput, out requestAmount);

        if (result == true)
        {
            if (this.DummyCashPresent < requestAmount)
            {
                // Show only message and no change in state
                return "Amount not present";
            }

            this.DummyCashPresent -= requestAmount;
            UpdateState();

            return string.Format(@"Amount of {0} has been withdrawn. Press Enter to proceed", requestAmount);
        }

        // Show only message and no change in state
        return "Invalid Amount";
    }

    private void UpdateState()
    {        
        Atm.currentState = new NoCashState(this);        
    }
}

The class for CASH_WITHDRAWN state:

class CashWithdrawnState : ATMState
{
    // This constructor will create new state taking values from old state
    public CashWithdrawnState(ATMState state)      
        :this(state.DummyCashPresent, state.Atm)
    {
        
    }

    // this constructor will be used by the other one
    public CashWithdrawnState(int amountRemaining, ATM atmBeingUsed)
    {
        this.Atm = atmBeingUsed;
        this.DummyCashPresent = amountRemaining;
    }

    public override string GetNextScreen()
    {
        UpdateState();
        return string.Format("Thanks you for using us, Amount left in ATM: {0}", this.DummyCashPresent.ToString());
    }

    private void UpdateState()
    {
        Atm.currentState = new NoCardState(this);
    }
}

Now with this design we are atually achieving the same functionality that we were achieving in the earlier example. This sure looks like more code but this approach is less error prone and using this approach the ATM class will need no modification. So if we need to add a new state then there will be minimal impact on code of existing state classes. So if I need to add a state for NO_CASH in this system, I just have to add a new concrete class that and hook it with the system.

class NoCashState : ATMState
{
    // This constructor will create new state taking values from old state
    public NoCashState(ATMState state)      
        :this(state.DummyCashPresent, state.Atm)
    {
        
    }

    // this constructor will be used by the other one
    public NoCashState(int amountRemaining, ATM atmBeingUsed)
    {
        this.Atm = atmBeingUsed;
        this.DummyCashPresent = amountRemaining;
    }

    public override string GetNextScreen()
    {            
        Console.WriteLine("ATM is EMPTY");
        Console.ReadLine();
        return string.Empty;
    }

    private void UpdateState()
    {
        // nothing here as someone will have to fill in cash and then
        // restart the atm, once restarted it will be in no card state
    }
}

And a minor modification in the UpdateState function of the CardValidatedState class.

private void UpdateState()
{
    if (this.DummyCashPresent == 0)
    {
        Atm.currentState = new NoCashState(this);
    }
    else
    {
        Atm.currentState = new CashWithdrawnState(this);
    }
}

Now let us test this system.

Before wrapping up let us look at the clas diagram of our application and compare it with the class diagram of GoF.

Point of interest

In this article we tried to get an overviwe of the state pattern and when could it be used. We also implemented as small application that contains a rudimentaty implementation of state pattern.

LINK: http://www.codeproject.com/Articles/489136/UnderstandingplusandplusImplementingplusStateplusP

A Simple Scheduler in C#

Introduction

One feature many Desktop and Web Applications require is to have a Scheduler. By Scheduler one means a framework which controls the parallel execution of Jobs. These Jobs can be executed only one or repeatedly. Therefore what one wishes is to have a framework which, in order to execute a Job (once or many times), it is necessary only to implement this very Job and hook it to the framework.

The goal of this article is to show how to develop this Scheduler and explaining in details the techniques and ideas behind this implementation. One may observe that, using the right design patterns and simple solutions, the outcome can be surprisingly straightforward.

The Scheduler described here is developed in a Microsoft .NET Library Project. A Microsoft .NET Console Project uses the DLL Library in order to implement and execute a few Jobs. The next sections of this article will show how exactly this is accomplished.

Background

Schedulers have always been a concern for architects when developing Enterprise Applications. Quite often the necessity for such a framework occurs because automation of parallel tasks aids immensely the user´s work, because it takes out of his or hers hand repetitive activities.

There are many ready-to-use solutions for that. On one hand, Java, for instance, provides a few schedulers, likeQuartz. On the other hand, Microsoft .NET developers can take advantage of Windows Services.

There are situations, however, that one may not be able to use these tools. For instance, one may have to deploy an ASP.NET Application in a Shared Server and the usage of Windows Services is simply not allowed.

Even if one can use frameworks to handle scheduling events, it may be quite interesting to see how a solution can be implemented for this matter. In this case, it is a combination of using Threads adequately and implementing the Template Method Design Pattern.

Architecture

In this section the architecture is discussed. Firstly, the class diagram is displayed and explained.

The class diagram consist of the framework (in the DLL Library) along with the execution program which dispatches the Jobs. The classes Job and JobManager encomposses the the framework; It is that simple, to implement this framework. The classes RepeatableJobRepeatableJob2 and SingleExecutionJob are Job implementations. Their names give away their main characteristics.

The Job class is to be implemented in order to be executed, either as a repeatable, or a single-execution task. TheJobManager class is responsible for gathering and executing all Jobs available (classes which extend Job).

The RepeatableJob and RepeatableJob2 are never-ending Jobs, meaning their code is always executed given fixed time-defined intervals.  The SingleExecutionJob has its code run one. The only purpose of these Jobs, is to print a message stating they have been executed. This illustrates beautifully their behavior in a console, when the program is executed.

The remaining class, Program, simply instantiates the JobManager and run it. The JobManager executes the Jobs asynchronously.

After understanding the general idea of the provided classes of the application, one can now comprehend the main thoughts which are the core of this Scheduler architecture. The JobManager, gathers all Job implementation of theJob class. These Job implementations must be within the .NET Project which uses the DLL holding the Scheduler framework. After gathering these Jobs, each of them is started in a new thread. The Job class has the methodExecuteTask() which triggers the Job task implementation. If the Job is to be executed once, after the task is completed the Job finishes its execution and the thread dies. In case the Job is repeatable, the task is executed repeatedly in intervals provided by the Job´s implementation. Note here that the Job class has some methods which are implemented and others which must be provided by its implementation. This technique falls into the Method Template Design Pattern.

The next sections, the most relevant parts of the code will be explained in more details so one can have a practical understanding of how to implement the Scheduler.

Using the code

The Job class is the obvious class to start discussing. One can have a better understanding of the framework simply by looking at it.

 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;

namespace SchedulerManager.Mechanism
{
    /// <summary>
    /// Classes which extend this abstract class are Jobs which will be
    /// started as soon as the application starts. These Jobs are executed
    /// asynchronously from the Web Application.
    /// </summary>
    public abstract class Job
    {
        /// <summary>
        /// Execute the Job itself, one ore repeatedly, depending on
        /// the job implementation.
        /// </summary>
        public void ExecuteJob()
        {
            if (IsRepeatable())
            {
                // execute the job in intervals determined by the methd
                // GetRepetionIntervalTime()
                while (true)
                {
                    DoJob();
                    Thread.Sleep(GetRepetitionIntervalTime());
                }
            }
            // since there is no repetetion, simply execute the job
            else
            {
                DoJob();
            }
        }

        /// <summary>
        /// If this method is overriden, on can get within the job
        /// parameters set just before the job is started. In this
        /// situation the application is running and the use may have
        /// access to resources which he/she has not during the thread
        /// execution. For instance, in a web application, the user has
        /// no access to the application context, when the thread is running.
        /// Note that this method must not be overriden. It is optional.
        /// </summary>
        /// <returns>Parameters to be used in the job.</returns>
        public virtual Object GetParameters()
        {
            return null;
        }

        /// <summary>
        /// Get the Job´s Name. This name uniquely identifies the Job.
        /// </summary>
        /// <returns>Job´s name.</returns>
        public abstract String GetName();

        /// <summary>
        /// The job to be executed.
        /// </summary>
        public abstract void DoJob();

        /// <summary>
        /// Determines whether a Job is to be repeated after a
        /// certain amount of time.
        /// </summary>
        /// <returns>True in case the Job is to be repeated, false otherwise.</returns>
        public abstract bool IsRepeatable();

        /// <summary>
        /// The amount of time, in milliseconds, which the Job has to wait until it is started
        /// over. This method is only useful if IJob.IsRepeatable() is true, otherwise
        /// its implementation is ignored.
        /// </summary>
        /// <returns>Interval time between this job executions.</returns>
        public abstract int GetRepetitionIntervalTime();
    }
}

This class is well commented so its reading is quite facilitated. The idea here is to provide everything a Job needs to be executed. The methods´ explanation will be given below:

  • DoJob() – Here is to be provided the task execution itself. This means all the work to be done has to be put inside this method.
  • IsRepeatable() – Determine whether the task is to be repeated or not.
  • GetRepetitionIntervalTime() – Return the interval, in milliseconds, which the Job has to wait until it is to be executed again, in case the Job is repeatable, obviously.
  • GetName() – Uniquely identifies the Job. It is very important that this name indeed is unique among the implemented Jobs in the assembly holding them, otherwise unexpected behavior is to occur.
  • GetParameters() – This method is to be implemented when one wishes to pass parameters to the task execution. In order to access the entered parameters, only simply has to call this method within the task implementation – DoJob() method.
  • ExecuteJob() – This method executes the task itself. It calls the DoJob() method. Note that in case the method is to be run repeatedly, the DoJob() is executed in a loop, otherwise it is called only one. Here is where the Method Template Design Pattern is applied. The ExecuteJob() method is executed based on its class´s method´s implementation.

The next class to be understood is the JobManager, which is displayed below:

 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
using log4net;
using SchedulerManager.Log4Net;

namespace SchedulerManager.Mechanism
{
    /// <summary>
    /// Job mechanism manager.
    /// </summary>
    public class JobManager
    {
        private ILog log = LogManager.GetLogger(Log4NetConstants.SCHEDULER_LOGGER);

        /// <summary>
        /// Execute all Jobs.
        /// </summary>
        public void ExecuteAllJobs()
        {
            log.Debug("Begin Method");

            try
            {
                // get all job implementations of this assembly.
                IEnumerable<Type> jobs = GetAllTypesImplementingInterface(typeof(Job));
                // execute each job
                if (jobs != null && jobs.Count() > 0)
                {
                    Job instanceJob = null;
                    Thread thread = null;
                    foreach (Type job in jobs)
                    {
                        // only instantiate the job its implementation is "real"
                        if (IsRealClass(job))
                        {
                            try
                            {
                                // instantiate job by reflection
                                instanceJob = (Job)Activator.CreateInstance(job);
                                log.Debug(String.Format(
                                  "The Job \"{0}\" has been instantiated successfully.", 
                                  instanceJob.GetName()));
                                // create thread for this job execution method
                                thread = new Thread(new ThreadStart(instanceJob.ExecuteJob));
                                // start thread executing the job
                                thread.Start();
                                log.Debug(String.Format(
                                  "The Job \"{0}\" has its thread started successfully.", 
                                  instanceJob.GetName()));
                            }
                            catch (Exception ex)
                            {
                                log.Error(String.Format("The Job \"{0}\" could not " + 
                                  "be instantiated or executed.", job.Name), ex);
                            }
                        }
                        else
                        {
                            log.Error(String.Format(
                              "The Job \"{0}\" cannot be instantiated.", job.FullName));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("An error has occured while instantiating " + 
                  "or executing Jobs for the Scheduler Framework.", ex);
            }

            log.Debug("End Method");
        }

        /// <summary>
        /// Returns all types in the current AppDomain implementing the interface or inheriting the type. 
        /// </summary>
        private IEnumerable<Type> GetAllTypesImplementingInterface(Type desiredType)
        {
            return AppDomain
                .CurrentDomain
                .GetAssemblies()
                .SelectMany(assembly => assembly.GetTypes())
                .Where(type => desiredType.IsAssignableFrom(type));

        }

        /// <summary>
        /// Determine whether the object is real - non-abstract, non-generic-needed, non-interface class.
        /// </summary>
        /// <param name="testType">Type to be verified.</param>
        /// <returns>True in case the class is real, false otherwise.</returns>
        public static bool IsRealClass(Type testType)
        {
            return testType.IsAbstract == false
                && testType.IsGenericTypeDefinition == false
                && testType.IsInterface == false;
        }
    }
}

Again, this class is well commented in order to ease the understanding. Have a look at the ExecuteAllJobs()method. This method, gathers all Job implementations from the assembly its being executed and run them in separate threads. Observe that this solution is quite simple. This solution does not have the dangers of deadlocks or complicated thread interactions. Furthermore, since each thread runs independently, it is very easy to debug and find errors in this framework.

One last think to be observed are the Jobs implementations. Below are displayed the SimgleExecutionJob and the  RepeatableJob ones.

 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SchedulerManager.Mechanism;

namespace SchedulerConsoleApp.Jobs
{
    /// <summary>
    /// A simple job which is executed only once.
    /// </summary>
    class SimgleExecutionJob : Job
    {
        /// <summary>
        /// Get the Job Name, which reflects the class name.
        /// </summary>
        /// <returns>The class Name.</returns>
        public override string GetName()
        {
            return this.GetType().Name;
        }

        /// <summary>
        /// Execute the Job itself. Just print a message.
        /// </summary>
        public override void DoJob()
        {
            System.Console.WriteLine(String.Format("The Job \"{0}\" was executed.", 
                                       this.GetName()));
        }

        /// <summary>
        /// Determines this job is not repeatable.
        /// </summary>
        /// <returns>Returns false because this job is not repeatable.</returns>
        public override bool IsRepeatable()
        {
            return false;
        }

        /// <summary>
        /// In case this method is executed NotImplementedException is thrown
        /// because this method is not to to be used. This method is never used
        /// because it serves the purpose of stating the interval of which the job
        /// will be executed repeatedly. Since this job is a single-execution one,
        /// this method is rendered useless.
        /// </summary>
        /// <returns>Returns nothing because this method is not to be used.</returns>
        public override int GetRepetitionIntervalTime()
        {
            throw new NotImplementedException();
        }
    }
}
 Collapse | Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SchedulerManager.Mechanism;

namespace SchedulerConsoleApp.Jobs
{
    /// <summary>
    /// A simple repeatable Job.
    /// </summary>
    class RepeatableJob : Job
    {
        /// <summary>
        /// Counter used to count the number of times this job has been
        /// executed.
        /// </summary>
        private int counter = 0;

        /// <summary>
        /// Get the Job Name, which reflects the class name.
        /// </summary>
        /// <returns>The class Name.</returns>
        public override string GetName()
        {
            return this.GetType().Name;
        }

        /// <summary>
        /// Execute the Job itself. Just print a message.
        /// </summary>
        public override void DoJob()
        {
            System.Console.WriteLine(String.Format(
              "This is the execution number \"{0}\" of the Job \"{1}\".", 
              counter.ToString(), this.GetName()));
            counter++;
        }

        /// <summary>
        /// Determines this job is repeatable.
        /// </summary>
        /// <returns>Returns true because this job is repeatable.</returns>
        public override bool IsRepeatable()
        {
            return true;
        }

        /// <summary>
        /// Determines that this job is to be executed again after
        /// 1 sec.
        /// </summary>
        /// <returns>1 sec, which is the interval this job is to be
        /// executed repeatadly.</returns>
        public override int GetRepetitionIntervalTime()
        {
            return 1000;
        }
    }
}

Note how straightforward they are: the SimgleExecutionJob provides its identifier based on its class name, implements the task, which is to print a message, and tells the Job is not repeatable. The RepeatableJob, does state the task is repetitive, provides the interval of execution, gives the class name to use as its identifier, and defines its task as a simple message printing.

Compiling and Running the Code

When one opens the code and tries to compile it, errors are displayed stating that there is no log4net libraries. This occurs because it is not allowed to upload .dll files in CodeProject articles, thus the log4net.dll was removed. Therefore, to fix the Solution Setup and build it correctly, download the log4net library clicking here.  After that, create a sub-directory called libraries in the folder SchedulerManager-noexe. Inside the directory libraries copy thelog4net.dll file one has just downloaded. Finally, refresh the SchedulerManager project references and you should see that the log4net reference has no warning flag. Compile the solution and run the SchedulerConsoleApp project.

Discussion

Firstly, note the simplicity of this solution, as stated before. Simply put, one gathers all Job implementations and executes them in separate threads. This straightforwardness allows one to easily add more functionalities to this framework.

In the subject of new features, one may consider having the Job´s requirements in a database. For instance, whether or not the job is repeatable, interval of execution, could be all stored in a database, each row identified by its unique name. This makes maintenance easier because in order to change their parameters execution no code change is necessary, simply database changes are needed.

Other features, such as, interface to handle the Job Management, the ability to run, pause and cancel a Job execution could also be implemented. Note however, that while these features seem nice and fancy, in most of applications there are rarely needed.

Many people argue that dealing with threads in Web Applications can be very dangerous because it may jeopardize the Application Sever. In this author´s experience, it could not be further from the truth, at least when one is working with Internet Information Services.

 

Link gốc: http://www.codeproject.com/Articles/591271/A-Simple-Scheduler-in-Csharp

The Template Method Design Pattern using C# .Net

First of all I’ll just put this pattern in context and describe its intent as in the GOF book:

Template Method:

Define the skeleton of an algorithm in an operation, deferring some steps to

Subclasses. Template Method lets subclasses redefine certain steps of an algorithm

without changing the Algorithm’s Structure. 

 

Usage:

When you are certain about the High Level steps involved in an Algorithm/Work flow you can use the Template Pattern which allows the Base Class to define the Sequence of the Steps but permits the Sub classes to alter the implementation of any/all steps.

Example in the .Net framework:

The most common example is the Asp.Net Page Life Cycle. The Page Life Cycle has a few methods which are called in a sequence but we have the liberty to modify the functionality of any of the methods by overriding them.

Sample implementation of Template Method Pattern:

Let’s see the class diagram first:

And here goes the code:

EmailBase.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     public abstract class EmailBase

10     {

11

12         public bool SendEmail()

13         {

14             if (CheckEmailAddress() == true) // Method1 in the sequence

15             {

16                 if (ValidateMessage() == true) // Method2 in the sequence

17                 {

18                     if (SendMail() == true) // Method3 in the sequence

19                     {

20                         return true;

21                     }

22                     else

23                     {

24                         return false;

25                     }

26

27                 }

28                 else

29                 {

30                     return false;

31                 }

32

33             }

34             else

35             {

36                 return false;

37

38             }

39

40

41         }

42

43         protected abstract bool CheckEmailAddress();

44         protected abstract bool ValidateMessage();

45         protected abstract bool SendMail();

46

47

48     }

49 }

50

EmailYahoo.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     public class EmailYahoo:EmailBase

10     {

11

12         protected override bool CheckEmailAddress()

13         {

14             Console.WriteLine(“Checking Email Address : YahooEmail”);

15             return true;

16         }

17         protected override bool ValidateMessage()

18         {

19             Console.WriteLine(“Validating Email Message : YahooEmail”);

20             return true;

21         }

22

23

24         protected override bool SendMail()

25         {

26             Console.WriteLine(“Semding Email : YahooEmail”);

27             return true;

28         }

29

30

31     }

32 }

33

 EmailGoogle.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     public class EmailGoogle:EmailBase

10     {

11

12         protected override bool CheckEmailAddress()

13         {

14             Console.WriteLine(“Checking Email Address : GoogleEmail”);

15             return true;

16         }

17         protected override bool ValidateMessage()

18         {

19             Console.WriteLine(“Validating Email Message : GoogleEmail”);

20             return true;

21         }

22

23

24         protected override bool SendMail()

25         {

26             Console.WriteLine(“Semding Email : GoogleEmail”);

27             return true;

28         }

29

30

31     }

32 }

33

Program.cs

    1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading.Tasks;

6

7 namespace TemplateMethod

8 {

9     class Program

10     {

11         static void Main(string[] args)

12         {

13             Console.WriteLine(“Please choose an Email Account to send an Email:”);

14             Console.WriteLine(“Choose 1 for Google”);

15             Console.WriteLine(“Choose 2 for Yahoo”);

16             string choice = Console.ReadLine();

17             EmailBase email;

17

18             if (choice == “1”)

19             {

20                 email = new EmailGoogle(); // Rather than newing it up here, you may use a factory to do so.

21                 email.SendEmail();

22

23             }

24             if (choice == “2”)

25             {

26                 email = new EmailYahoo(); // Rather than newing it up here, you may use a factory to do so.

27                 email.SendEmail();

28             }

29         }

30     }

31 }

32

Final Words:

It’s very obvious that why the Template Method Pattern is a popular pattern, everything at last revolves around Algorithms and if you are clear with the steps involved it makes real sense to delegate the duty of implementing the step’s functionality to the sub classes.

Link gốc: http://weblogs.asp.net/saurabhnijhawan/archive/2012/10/15/the-template-method-design-pattern-using-c-net.aspx

Template Method in C#

definition

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.Frequency of use:   medium

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 ot 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.

Show code

// Template Method pattern — Structural example

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.

Hide code

// Template Method pattern — Real World example

using System;

using System.Data;

using System.Data.OleDb;

namespace DoFactory.GangOfFour.Template.RealWorld

{

/// <summary>

/// MainApp startup class for Real-World

/// Template Design Pattern.

/// </summary>

class MainApp

{

/// <summary>

/// Entry point into console application.

/// </summary>

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>

abstract class DataAccessObject

{

protected string connectionString;

protected DataSet dataSet;

public virtual void Connect()

{

// Make sure mdb is available to app

connectionString =

“provider=Microsoft.JET.OLEDB.4.0; ” +

“data source=..\\..\\..\\db1.mdb”;

}

public abstract void Select();

public abstract void Process();

public virtual void Disconnect()

{

connectionString = “”;

}

// The ‘Template Method’

public void Run()

{

Connect();

Select();

Process();

Disconnect();

}

}

/// <summary>

/// A ‘ConcreteClass’ class

/// </summary>

class Categories : DataAccessObject

{

public override void Select()

{

string sql = “select CategoryName from Categories”;

OleDbDataAdapter dataAdapter = new OleDbDataAdapter(

sql, connectionString);

dataSet = new DataSet();

dataAdapter.Fill(dataSet, “Categories”);

}

public override void Process()

{

Console.WriteLine(“Categories —- “);

DataTable dataTable = dataSet.Tables[“Categories”];

foreach (DataRow row in dataTable.Rows)

{

Console.WriteLine(row[“CategoryName”]);

}

Console.WriteLine();

}

}

/// <summary>

/// A ‘ConcreteClass’ class

/// </summary>

class Products : DataAccessObject

{

public override void Select()

{

string sql = “select ProductName from Products”;

OleDbDataAdapter dataAdapter = new OleDbDataAdapter(

sql, connectionString);

dataSet = new DataSet();

dataAdapter.Fill(dataSet, “Products”);

}

public override void Process()

{

Console.WriteLine(“Products —- “);

DataTable dataTable = 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
SeafoodProducts —-
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

 

Link gốc: http://dofactory.com/Patterns/PatternTemplate.aspx#_self1