Showing posts with label OOP. Show all posts
Showing posts with label OOP. Show all posts

Feb 29, 2008

5 minutes C# to build a Zoo with Marker Interfaces.

First of all what is marker interface?
A marker interface is an empty interface which defines no fields, but is only there for reference.

Let's start with the case study and we will go through the example and explain everything.


Case Study : Build a simple Zoo program.
You have a Zoo with few animals - those animals are only fishes and birds. As this Zoo is relatively small it has only one employee to feed all the animals with the appropriate food. The fishes eat food which we will refer to as "fishfood" and the birds eat a food which we will refer to as "grains".

To accomplish this we may create an interface, which identifies the things that are common for both types of animals in the Zoo.

IAnimal.cs

using System;
using
System.Collections.Generic;
using System.Text;

namespace MarkerInterface.Objects
{
  
interface IAnimal
   {
    
void Feed(FoodType food);
    
bool Hungry
     {
        
set;
        
get;
     }
   }
}

Ok, we gave the animals the ability to eat, but how will the employee identify what kind of food to feed them with?

Let's first define an enumerator to hold the food types:

Food.cs:

using System;
using System.Collections.Generic;
using System.Text;

namespace MarkerInterface.Objects
{
  
public enum FoodType
   {
     Grains,
     Fishfood
   }
}

Ok, we have the food types now. In order to split the animals in the Zoo in two separate groups we are going to use the Marker Interface, we will define two interfaces to mark which animal is fish and which is bird.

IBird.cs:

using System;
using System.Collections.Generic;
using System.Text;

namespace MarkerInterface.Objects
{
  
interface IBird : IAnimal
   {
    
   }
}

Now let's do the same for the fieshes:

using System;
using System.Collections.Generic;
using System.Text;

namespace MarkerInterface.Objects
{
  
interface IFish : IAnimal
   {
    
   }
}

Now let's have two concrete animals - one for each type:

Heller.cs:

using System;
using System.Collections.Generic;
using System.Text;

namespace MarkerInterface.Objects.Animals
{
  
class Heller : IFish
   {
     #region IFish Members
    
private bool hungry = false;
    
public void Feed(FoodType food)
     {
        
if (food != FoodType.Fishfood)
        {
          
throw new ArgumentException("Heller is a fish and eats only fishfood.");
        }
        
else
        {
          
this.hungry = false;
        }
     }

     #endregion

     #region
IAnimal Members

    
public bool Hungry
     {
        
get
        {
          
return this.hungry;
        }
        
set
        {
          
this.hungry = value;
        }
     }

     #endregion
   }
}

Chicken.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace MarkerInterface.Objects.Animals
{
  
class Chicken : IBird
   {

     #region IBird Members
    
    
bool hungry = false;

    
public void Feed(FoodType food)
     {
        
if (food != FoodType.Grains)
        {
          
throw new ArgumentException("The chicken only eats grains.");
        }
        
else
        {
          
this.hungry = false;
        }
     }

    
public bool Hungry
     {
        
get { return this.hungry; }
        
set { this.hungry = value; }
     }

     #endregion
   }
}

Let's have one employee to feed the animals:

ZooEmployee.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace MarkerInterface.Objects
{
  
class ZooEmployee
   {
    
public delegate void OnAnimalFeeded(string Animal, string FoodType);
    
public event OnAnimalFeeded AnimalFeeded;

    
public void FeedAnimals(List<IAnimal> animals)
     {
        
foreach (IAnimal animal in animals)
        {
          
if (animal is IFish)
           {
             animal.Feed(
FoodType.Fishfood);
            
this.AnimalFeeded(animal.GetType().Name, "fish food");
           }
          
if (animal is IBird)
           {
             animal.Feed(
FoodType.Grains);
            
this.AnimalFeeded(animal.GetType().Name, "grains");
           }
        }
     }
   }
}

NOTE: I added the OnAnimalFeeded delegate and the AnimalFeeded event, so the Zoo employee can report to us when it has feeded an animal.

Let's define the Zoo class:

Zoo.cs

namespace MarkerInterface.Objects
{
  
class Zoo
   {
    
List<IAnimal> animals = new List<IAnimal>();
    
List<ZooEmployee> employees = new List<ZooEmployee>();

    
public Zoo()
     {
        animals.Add(
new Animals.Chicken());
        animals.Add(
new Animals.Heller());

        
ZooEmployee employee = new ZooEmployee();
        
this.employees.Add(employee);
     }

    
public List<IAnimal> Animals
     {
        
get { return this.animals; }
     }
    
public List<ZooEmployee> Employees
     {
        
get { return this.employees; }
     }
   }
}

Now, in the main form of the program we will instantiate the Zoo class, and call its employee to feed all the animals.

On the form I added one button and one RichTextbox. When I click the button the following code will get executed:

        Objects.
Zoo zoo = new MarkerInterface.Objects.Zoo();
        zoo.Employees[0].AnimalFeeded +=
new MarkerInterface.Objects.ZooEmployee.OnAnimalFeeded(Form1_AnimalFeeded);
        zoo.Employees[0].FeedAnimals(zoo.Animals);

What are we doing here - we are simply creating a Zoo, we are using it's first employee (as we said it will always be exactly one emplyee) AnimalFeeded event to report when what animal is feeded and with what food and we are then asking the employee to feed the animals.

The marker interfaces here are used in the ZooEmployee.FeedAnimals() method to help the employee decide which type of food to give to each animal.

As the Chicken inherits from the IBird the employee will feed it with grains. As the Heller inherits from IFish it will be feeded with fish food.

Here is the Form1_AnimalFeeded which is fired each time the employee feeds animals. It will be used to display in the RichTextBox what is our employee doing at the moment:

    
void Form1_AnimalFeeded(string Animal, string FoodType)
     {
        
this.rtbAnimalsFeeded.AppendText(Animal + " was feeded with " + FoodType + "\n");
     }

Here is how it looks like after it was runed:



Hope you understood it ;).