views:

811

answers:

3

Say for example you have a base abstract class

public abstract Foo
{
  IFlyable _fly;
  ISwimmable _swim;

  void performSwim()
  {
    _swim.swim();
  }

 void performFly()
 {
   _fly.fly();
 }
}

And have behaviors/algorithm that you will have in your system

interface IFlyable { void fly(); }
interface ISwimmable { void swim(); }
interface IVoteable { void vote(); }

etc etc

Now you have multiple class that implement it, with concrete of IFlyable, ISwimmable etc

class Bar: Foo { _swim = new ConcerteSwim(); }
class Baz: Foo { _fly = new ConcreteFly(); }

etc etc

One is using the strategy pattern in the base class of Foo to swap in the behaviours.

We could also use the decorator pattern to wrap it with certain behavior but since the decorator wraps it with base class, how do we actually allow the open close principle to work without touching the base class if we later on add more behaviors to objects. Since these behavior might have different signatures as we add more, rather than just for example like calling in decorator

void performSwim()
{
     swimWithMoreSpeed() + foo.performSwim()
}

I guess my question is if I add more behavior, how can I not modify the base class and still be able to say add IWeaponBehavior, ISomeBehaviour to a class.

for example I want to have a class

public class XYF: Foo
{

}

But I want to give it some behavior of ISomeBehaviour, is there a way I could say wrap it with these kinds of behaviour, or more like here is an ConcreteFoo wrap it with these behaviours and now do stuff rather than implementing the interface on concrete xyz although that makes you implementing so many kinds of concretebehaviour class like swimbehaviour, nullbehaviour etc but there is no way out of it.

Is there a way to do this in design patterns? It almost seems like a hybrid of patterns.

I know it almost seems like if it walks like a duck and quacks like a duck but requires battery then you have something wrong with abstraction.

Hope this make sense.

A: 

So here's my take on this:

public enum ActionType
{
   Swim, Vote, Fly
};

public interface IBehavior
{
   public boolean ActionReady;
   public ActionType _type;

   public void performMyAction();
}

public abstract Foo
{
  IBevahior[] behaviors;

  // if you want to keep track of behavior states as on or off
  void perform()
  {
    for(int i = 0; i< behaviors.length; i++)
    {
       if(behaviors[i].ActionReady)
       {
          behaviors[i].performMyAction();
       }
    }
  }

  // if you want to call behaviors individually
  void performType(ActionType type)  // however you want to make the distinction
  {
     for(int i = 0; i < behaviors.length; i++)
     {
        if(behaviors[i].type = type)
        {
            behaviors[i].performMyAction();
        }
     }
  }
}

and then have your interfaces like ISwimmable, etc inherit from IBehavior.

notnot
But one would get into a giant switch statement for the type and each one might have a different performMyAction.
In this case, it would make sense for the child classes to have member variables for potential parameters which would be used inside of the performMyAction() call. Not the prettiest, but it is very flexible.myFoo.performType(ActionType.Swim);
notnot
+2  A: 

Try the decorator pattern. To support a new behavior, you would just implement a new class that inherits from Foo, implements IWeaponBehavior, and decorates another Foo object. Then you can now use the WeaponDecorator as a Foo or IWeaponBehavior and still have access to the base Foo that it decorates.

Base class:

public abstract Foo { void Jump(); }

Concrete subclasses with base behavior:

public Bar : Foo { void Jump() { /* jump! */ } }
public Baz : Foo { }

Behavior interfaces:

interface IFlyable { void Fly(); }
interface ISwimmable { void Swim(); }

Decorator subclasses with behavior:

public FlyableFoo : Foo, IFlyable
{
    public Foo Base { get; set; }
    public FlyableFoo(Foo base) { Base = base; }
    void Fly() { Base.Jump(); /* fly! */ }
}

Now we can make any Foo fly, using its particular implementation of Jump():

Baz baz = new Baz();
FlyableFoo flybaz = new FlyableFoo(baz);
flybaz.Fly();
dahlbyk
can you give an example of it.
Hope that helps..
dahlbyk
A: 

How about the visitor pattern? It allows implementors of your base class to vary behaviours without forcing the base class to change for each new implementation:

public interface IFlyable { void fly(); }
public interface ISwimmable { void swim(); }
public interface IVoteable { void vote(); }

public abstract class Animal
{
    public abstract void Accept(AnimalVisiter Visitor);
    //some common behaviour is here
    public bool LegsKicking { get; set; }
    public bool ArmsFlapping { get; set; }
}

//This class now absorbs new responisbilities, so base class doesn't have to
public class AnimalVisiter
{
    public void Visit(ISwimmable Subject)
    {
        Subject.swim();
    }

    public void Visit(IVoteable Subject)
    {
        Subject.vote();
    }

    public void Visit(IFlyable Subject)
    {
        Subject.fly();
    }
}

public class SwimmingHuman : Animal, ISwimmable
{
    public void swim()
    {
        LegsKicking = true;
    }

    public override void Accept(AnimalVisiter Visitor)
    {
        Visitor.Visit(this);
    }
}

public class VotingHuman : Animal, IVoteable
{

    public override void Accept(AnimalVisiter Visitor)
    {
        Visitor.Visit(this);
    }

    public void vote()
    {
        VoteCast = true;
    }
    //some specific behaviour goes here
    public bool VoteCast { get; set; }
}

public class SwimmingTiger : Animal, ISwimmable
{

    public void swim()
    {
        LegsKicking = true;
        //also wag tail, flap ears
    }

    public override void Accept(AnimalVisiter Visitor)
    {
        Visitor.Visit(this);
    }
}
Noel Kennedy