Story about Strategy Design Pattern (Behavioural)
created by Vladimir Minkin
Photo by Maarten van den Heuvel
Inheritance is a mechanism in which one object acquires all the properties and behaviors of parent object.
Vehicle
go()
abstract
RacingCar
@Override go()
Helicopter
Override go()
CityCar
beep()
Override beep()
Apache
Override go()
Jet
Override go()
Override beep()
Overuse of Inheritance. To many objects that needs to be maintainable with small changes in each.
Hard for runtime changes.
You can extend or alter them without affecting the rest of your code
Programming to Interface. Take code that varies and extract it to Algorithm objects.
Vehicle
Algorithm variable
Algorithm object 1
Algorithm object 2
Algorithm object 3
Algorithm object 4
polymorphic behavior
Defines a "family" of algorithms, encapsulates them, and makes them interchangeable with an Interface.
Client don't need to know details of how the behaviors implemented.
An algorithm can be selected and exchanged at run-time.
public interface IMovable {
void move(Vector2 position);
}
public class AviationMoveAlgorithm : MonoBehaviour, IMovable
{
public void move(Vector2 position)
{
this.transform.position = position;
Debug.Log(string.Format("> Move Aviation : is moving by flying"));
}
}
public class InfantryMoveAlgorithm : MonoBehaviour, IMovable
{
public void move(Vector2 position)
{
float distance = Vector3.Distance(transform.position, new Vector3(position.x, position.y));
float time = distance / _speed;
Debug.Log(string.Format("> Move Infantry : is moving by going : " + time));
...
}
}
public class JumpMoveAlgorithm : MonoBehaviour, IMovable
{
...
public void move(Vector2 position)
{
_path.Enqueue(position);
if (isTweenInAvailable) {
MoveToDestination();
}
Debug.Log(string.Format("Terran Infantry : is moving by jumping" ));
}
}
- Extract Interface
- Implements Algorithms
public abstract class Unit : MonoBehaviour
{
static public Type getTypeForMoveAlgorithm(MoveAlgorithm input)
{
switch (input) {
default:
case MoveAlgorithm.Null: return typeof(NullMoveAlgorithm);
case Unit.MoveAlgorithm.Aviation: return typeof(AviationMoveAlgorithm);
case Unit.MoveAlgorithm.Jump: return typeof(JumpMoveAlgorithm);
case Unit.MoveAlgorithm.Infantry: return typeof(InfantryMoveAlgorithm);
case Unit.MoveAlgorithm.Wiggle: return typeof(WiggleMoveAlgorithm);
}
}
public enum MoveAlgorithm {
Null,
Aviation,
Infantry,
Jump,
Wiggle
};
private IMovable _moveAlgorithm = new NullMoveAlgorithm();
virtual public void move(Vector2 position) { _moveAlgorithm.move(position); }
public MoveAlgorithm GetMoveAlgorithm() { return _moveAlgorithmEnum; }
public void SetMoveAlgorithm(MoveAlgorithm value)
{
_moveAlgorithm = (IMovable)this.gameObject.AddComponent(getTypeForMoveAlgorithm(value));
Debug.Log("> Unit -> SetMoveAlgorithm: _moveAlgorithm " + _moveAlgorithm);
}
}
- Abstract class
public class Battlecruiser : Unit
{
void Start ()
{
Name = "Battlecruiser";
SetMoveAlgorithm(Unit.MoveAlgorithm.Aviation);
}
}
public class Goliath : Unit
{
void Start ()
{
Name = "Goliath";
SetMoveAlgorithm(Unit.MoveAlgorithm.Jump);
}
}
public class Marine : Unit
{
void Start ()
{
Name = "Marine";
SetMoveAlgorithm(Unit.MoveAlgorithm.Infantry);
}
}
public class Medik : Unit
{
void Start ()
{
Name = "Medik";
SetMoveAlgorithm(MoveAlgorithm.Null);
}
}
- Concrete classes