Tuesday, August 7, 2007

Polymorphism

Polymorphism Overview:

Through inheritance, a class can be used as more than one type; it can be used as its own type, any base types, or any interface type if it implements interfaces. This is called polymorphism.

When a derived class inherits from a base class, it gains all the methods, fields, properties and events of the base class. To change the data and behavior of a base class, you have two choices: you can replace the base member with a new derived member, or you can override a virtual base member.
Replacing a member of a base class with a new derived member requires the new keyword. If a base class defines a method, field, or property, the new keyword is used to create a new definition of that method, field, or property on a derived class. The new keyword is placed before the return type of a class member that is being replaced. For example:

-----------------------------Example 1---------------------------------------------------------
#region [TestingPolyNew]

///
/// Testing Polymorphism with new keyword
/// Replacing a member of a base class with a new derived member requires the new keyword.
/// If a base class defines a method, field, or property, the new keyword is used to create a new definition of that method, field, or property on a derived class.
///

///

public class CBaseClass
{
public void DoWork() { }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
public class CDerivedClass : CBaseClass
{
public new void DoWork() { }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
public class CTestPoly
{
public void Test()
{
//When the new keyword is used, the new class members are called instead of the base class members
//that have been replaced. Those base class members are called hidden members. Hidden class members
//can still be called if an instance of the derived class is cast to an instance of the base class.
//For example:
CDerivedClass B = new CDerivedClass();
B.DoWork(); // Calls the new method.
CBaseClass A = (CBaseClass)B;
A.DoWork(); // Calls the old method.
}
static void Main()
{
CTestPoly objTestPoly = new CTestPoly();
objTestPoly.Test();
}
}
#endregion [TestingPolyNew]


-----------------------------Example 2--------------------------------------------------------

In order for an instance of a derived class to completely take over a class member from a base class, the base class has to declare that member as virtual.

A derived class then has the option of using the override keyword, instead of new, to replace the base class implementation with its own. For example:


#region [TestingVirtualPoly]
///
/// Testing polymorphism with virtual/override
///

/// In order for an instance of a derived class to completely take over a class member from a base class,
/// the base class has to declare that member as virtual. A derived class then has the option of using the
/// override keyword, instead of new, to replace the base class implementation with its own.
public class CA
{
public virtual void DoWork() { }
public virtual int WorkProperty
{
get { return 0; }
}
}
public class CB : CA
{
public override void DoWork() { }
public override int WorkProperty
{
get { return 0; }
}
}
public class CTestVirutalPoly
{
public void Test()
{
CB B = new CB();
B.DoWork(); // Calls the new method.
CA A = (CA)B;
A.DoWork(); // Also calls the new method.
}
static void Main()
{
CTestVirutalPoly objVP = new CTestVirutalPoly();
objVP.Test();
}
}
#endregion [TestingVirtualPoly]

-----------------------------Example 3--------------------------------------------------------

C# enables methods in derived classes to have the same name as methods in base classes—as long as you are very specific about how the new method should be treated. The following example demonstrates the use of the new and override keywords.

First we declare three classes: a base class called Car, and two classes that derive from it, ConvertibleCar and Minivan. The base class contains a single method, DescribeCar, which sends a description of the car to the console. The derived class methods also include a method called DescribeCar, which displays their unique properties. These methods also call the base class DescribeCar method to demonstrate how they have inherited the properties of the Car class.

In order to highlight the difference, the ConvertibleCar class is defined with the new keyword, while the Minivan class is defined with override.


#region [WhenToUseNewOverride]
///
/// In order to highlight the difference, the ConvertibleCar class is defined with the new keyword,
/// while the Minivan class is defined with override.
///

public class Car
{
public virtual void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
}
}
public class ConvertibleCar : Car
{
public new virtual void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("A roof that opens up.");
}
}
public class MiniVan : Car
{
public override void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("Carries seven people.");
}
}
public class CDescribeCars
{
public void Describe()
{
Car car1 = new Car();
car1.DescribeCar();
System.Console.WriteLine("----------------------");
ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
System.Console.WriteLine("----------------------");
MiniVan car3 = new MiniVan();
car3.DescribeCar();
System.Console.WriteLine("----------------------");
}
public void Test2()
{
Car[] cars = new Car[3];
cars[0] = new Car();
cars[1] = new ConvertibleCar();
cars[2] = new MiniVan();
foreach (Car vehicle in cars)
{
System.Console.WriteLine("Car object: " + vehicle.GetType());
vehicle.DescribeCar();
System.Console.WriteLine("----------");
}

}
static void Main()
{
CDescribeCars objCars = new CDescribeCars();
objCars.Describe();
//output
//Four wheels and an engine.
//----------
//Four wheels and an engine.
//A roof that opens up.
//----------
//Four wheels and an engine.
//Carries seven people.
//----------
objCars.Test2();
//output
//Notice how the ConvertibleCar description is not what you might expect.
//As the new keyword was used to define this method, the derived class method is not
//called—the base class method is called instead. The Minivan object correctly calls
//the overridden method, producing the results we expected.

//Car object: YourApplication.Car
//Four wheels and an engine.
//----------
//Car object: YourApplication.ConvertibleCar
//Four wheels and an engine.
//----------
//Car object: YourApplication.Minivan
//Four wheels and an engine.
//Carries seven people.
Console.Read();
}
}
#endregion[WhenToUseNewOverride]

Monday, July 30, 2007

Abstract Factory



The Abstract Factory is intended to provide a single interface for clients to use when they need to create a family of related objects without having to specify concrete classes. For example, imagine a system that needs to implement platform-specific user interface objects (menus, toolbars, and so forth) for several different platforms. Abstract Factory simplifies the interface for the client by localizing all of the initialization strategies within a single class, the Abstract Factory. The pattern works to ensure that all the strategies can work together correctly.

To understand Abstract Factory, examine the class diagram shown in the above figure. Note that there are two separate hierarchies. The first represents the various abstractions the client has interest in. For each abstraction, there exists an abstract class definition (AbstractClass1, AbstractClass2, and so on), and the subclasses that provide the concrete implementations (ConcreteClass1A, ConcreteClass1B, and so forth). In the second hierarchy, an abstract AbstractFactory class is defined to provide the interface for each class that is responsible for creating the members of a particular family. For example, ConcreteFactoryB is responsible for creating objects from classes ConcreteClass1B, ConcreteClass2B, and the like.

All the client needs to worry about is which family of objects it is interested in creating and calling the appropriate Factory method. Because the client only knows about the abstract interface, it can interact with objects from different families without having to know about their internal implementation details. This approach has the benefit that the family can be allowed to grow without the need to modify the client.

The primary drawback of AbstractFactory is that it can limit your flexibility when you want to take advantage of a specific capability a family may have. This is because you must provide a common interface across all families, even if some of them do not have this capability.

Example:


Participants

The classes and/or objects participating in this pattern are:
  • AbstractFactory (ContinentFactory) - declares an interface for operations that create abstract products
  • ConcreteFactory (AfricaFactory, AmericaFactory) - implements the operations to create concrete product objects
  • AbstractProduct (Herbivore, Carnivore) - declares an interface for a type of product object
  • Product (Wildebeest, Lion, Bison, Wolf) - defines a product object to be created by the corresponding concrete factory & implements the AbstractProduct interface
  • Client (AnimalWorld) - uses interfaces declared by AbstractFactory and AbstractProduct classes


Design Patterns

Before I start, I would like to bring to your notice that I have taken most of the stuff from these sites:


What Are Design Patterns and Do I Need Them?

Software professionals may be familiar with the term "Design Patterns," but many have no idea of where they come from and what they truly are. Consequently, some do not see the value and benefits design patterns bring to the software development process, especially in the areas of maintenance and code reuse. This article will bridge this gap by defining design patterns from a historical perspective. It will also summarize the salient features of a typical design pattern and arrive at a working definition so that you will know what they are and what to expect when you incorporate them into your designs. Finally, it will explicitly summarize the benefits design patterns bring to software development and why you should incorporate them into your work. Subsequent articles will present more detailed descriptions of some of the more common design patterns, and how they can be applied to software development on the .NET platform.

What Are Design Patterns and Where Do They Come From?

Design patterns are commonly defined as time-tested solutions to recurring design problems. The term refers to both the description of a solution that you can read, and an instance of that solution as used to solve a particular problem. (I like the analogy of comparing design patterns to a class and an object instance of the class. Each is a different way to represent a thing.) Design patterns have their roots in the work of Christopher Alexander, a civil engineer who wrote about his experience in solving design issues as they related to buildings and towns. It occurred to Alexander that certain design constructs, when used time and time again, lead to the desired effect. He documented and published the wisdom and experience he gained so that others could benefit. About 15 years ago, software professionals began to incorporate Alexander's principles into the creation of early design pattern documentation as a guide to novice developers. This early work led others to also write about design patterns and culminated in the publication of Design Patterns: Elements of Reusable Object-Oriented Software in 1995 by Eric Gamma, Richard Helm, Ralph Johnson, and John Vlissides. This book is considered to be the "coming out" of design patterns to the software community at large and has been influential in the evolution of design patterns since. Design Patterns described 23 patterns that were based on the experience of the authors at that time. These patterns were selected because they represented solutions to common problems in software development. Many more patterns have been documented and cataloged since the publishing of Design Patterns. However, these 23 are probably the best known and certainly the most popular. Design patterns are represented as relationships between classes and objects with defined responsibilities that act in concert to carry out the solution. To illustrate a design pattern, consider the Adapter pattern, one of the original 23 patterns described in Design Patterns. Adapter provides a solution to the scenario in which a client and server need to interact with one another, but cannot because their interfaces are incompatible. To implement an Adapter, you create a custom class that honors the interface provided by the server and defines the server operations in terms the client expects. This is a much better solution than altering the client to match the interface of the server.The design pattern community is growing both in membership and coverage. The pattern literature describes new patterns that solve emerging issues related to technical advancements. As a software professional, you are the beneficiary of this body of knowledge. To use these patterns, you will need to learn them and become familiar with them so you will know which pattern to pull from your toolbox when a design issue arises. Many patterns have been documented over the years. They have been classified in different ways by different authors. Take the time to learn different ways to classify design patterns because you will gain greater insight into them. As you learn more and more patterns, it would be a good idea to develop your own classification system; one reflecting the way you utilize them.

Structure of a Design Pattern

Design pattern documentation is highly structured. The patterns are documented from a template that identifies the information needed to understand the software problem and the solution in terms of the relationships between the classes and objects necessary to implement the solution. There is no uniform agreement within the design pattern community on how to describe a pattern template. Different authors prefer different styles for their pattern templates. Some authors prefer to be more expressive and less structured, while others prefer their pattern templates to be more precise and high grain in structure. We will use the template first described by the authors of Design Patterns to illustrate a template.

Pattern Name - Describes the essence of the pattern in a short, but expressive, name

Intent - Describes what the pattern does

Also Known As - List any synonyms for the pattern

Motivation - Provides an example of a problem and how the pattern solves that problem

Applicability - Lists the situations where the pattern is applicable

Structure - Set of diagrams of the classes and objects that depict the pattern

Participants - Describes the classes and objects that participate in the design pattern and their responsibilities

Collaborations - Describes how the participants collaborate to carry out their responsibilities

Consequences - Describes the forces that exist with the pattern and the benefits, trade-offs, and the variable that is isolated by the pattern

This template captures the essential information required to understand the essence of the problem and the structure of the solution. Many pattern templates have less structure than this, but basically cover the same content.


Benefits of Design Patterns

Design patterns have two major benefits. First, they provide you with a way to solve issues related to software development using a proven solution. The solution facilitates the development of highly cohesive modules with minimal coupling. They isolate the variability that may exist in the system requirements, making the overall system easier to understand and maintain. Second, design patterns make communication between designers more efficient. Software professionals can immediately picture the high-level design in their heads when they refer the name of the pattern used to solve a particular issue when discussing system design.


The 23 common Design Patterns


  1. Abstract Factory
  2. Adapter
  3. Bridge
  4. Builder
  5. Chain of Responsibility
  6. Command
  7. Composite
  8. Decorator
  9. Facade
  10. Factory Method
  11. Flyweight
  12. Interpreter
  13. Iterator
  14. Mediator
  15. Memento
  16. Observer
  17. Prototype
  18. Proxy
  19. Singleton
  20. State
  21. Strategy
  22. Template Method
  23. Visitor

Examples to follow soon...