Strategy Pattern
Taking Alastair Patrick’s example of applying patterns to game making I present the strategy pattern. The strategy pattern encapsulates behavior allowing flexibility and object composition. This means a group of classes (as ships) can have some behavior in common, but also room for different flavors without having a lot of overrides and duplicate code. Here’s an example in code. Note, I’ve even written it so the behavior can be changed at runtime!
public interface AttackBehavior
{
void Attack();
}
public class AttackWithNoWeapon : AttackBehavior
{
public AttackWithNoWeapon()
{
//
// TODO: Add constructor logic here
//
}
public void Attack()
{
Console.Out.WriteLine( "No weapon to attack with." );
}
}
public class AttackWithRedLaser : AttackBehavior
{
public AttackWithRedLaser()
{
//
// TODO: Add constructor logic here
//
}
public void Attack()
{
Console.Out.WriteLine( "Firing red lasers." );
}
}
public class AttackWithReinforcedIceProjectile : AttackBehavior
{
public AttackWithReinforcedIceProjectile()
{
//
// TODO: Add constructor logic here
//
}
public void Attack()
{
Console.Out.WriteLine( "Firing Reinforced Ice Projectiles " );
}
}
public interface FlyBehavior
{
void Fly();
}
public class FlyWithIonEngines : FlyBehavior
{
public FlyWithIonEngines()
{
//
// TODO: Add constructor logic here
//
}
public void Fly()
{
Console.Out.WriteLine( "Moved 4 parsecs." );
}
}
public class FlyWithNoEngines : FlyBehavior
{
public FlyWithNoEngines()
{
//
// TODO: Add constructor logic here
//
}
public void Fly()
{
Console.Out.WriteLine( "Movement determined by gravity and inertia." );
}
}
public class FlyWithSolarSails : FlyBehavior
{
public FlyWithSolarSails()
{
//
// TODO: Add constructor logic here
//
}
public void Fly()
{
Console.Out.WriteLine( "Low Solar Wind, move .5 parsecs." );
}
}
public abstract class Ship
{
protected FlyBehavior flyBehavior = null;
protected AttackBehavior attackBehavior = null;
public Ship()
{
}
public abstract void Display();
public void PerformFly()
{
flyBehavior.Fly();
}
public void PerformAttack()
{
attackBehavior.Attack();
}
public void Repair()
{
Console.Out.WriteLine( "Repair teams dispatched, 10% improvement." );
}
public void SetFlyBehavior( FlyBehavior fb )
{
flyBehavior = fb;
}
public void SetAttackBehavior( AttackBehavior ab )
{
attackBehavior = ab;
}
}
public class TerranMarkI : Ship
{
public TerranMarkI()
{
flyBehavior = new FlyWithIonEngines();
attackBehavior = new AttackWithRedLaser();
}
public override void Display()
{
Console.Out.WriteLine( "This is a Terran Mark I ship." );
}
}
public class NeiwckronMkI : Ship
{
public NeiwckronMkI()
{
SetAttackBehavior( new AttackWithNoWeapon() );
SetFlyBehavior( new FlyWithIonEngines() );
}
public override void Display()
{
Console.Out.WriteLine( "A Neiwckron Mark I ship." );
}
}
public class TheMain
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Ship s1 = new TerranMarkI();
s1.PerformAttack();
s1.PerformFly();
Ship s2 = new NeiwckronMkI();
s2.PerformFly();
s2.SetFlyBehavior( new FlyWithSolarSails() );
s2.PerformFly();
}
}