3. Using OOPS
• Using traditional OOP we take common features of all Cats and put them in a base class. Since the
requirement mentioned simulation of different Cats we then create different Cat classes (Siamese,
Persian)
• Persian Class will implement its own Display function and so too Siamese.
4. Change is always a Constant
• The requirements change after a client review
meeting and now they want to add
functionality that will simulate eating
attribute. So all Cats need to eat.
5. What do we do
• Using power of inheritance, I just have to add
a method called Eat() to the base class. Right ?
6.
7. • What if tomorrow requirement changes to say that
they want to add a feature to simulate toy Cats. The
client wants to make their simulation kids friendly.
• We know there is a potential problem that a Toy Cat
can possibly Purr, Walk, (battery operated) but can it
eat?
8. • So again we can use the power of inheritance
and override the functions that we don’t want
to use and ask it to not implement anything.
10. Sharpen What you learnt
• Which of the following are disadvantages of
using inheritance to provide Cat type
behavior? (Choose all that apply.)
A. Code is duplicated across subclasses.
B. Runtime behavior changes are difficult.
C. We can’t make Cats dance.
D. Hard to gain knowledge of all Cats behaviors.
E. Cats can’t Purr and run at the same time.
F. Changes can unintentionally affect other Cats
11. Interface – How would it help
• Take what varies and “encapsulate”
• Separate the “parts that change from those
that stay the same”
• Create two sets of Interfaces (totally apart
from Cat), one for IEat and one for IPurr.
• Each set of concrete classes will hold all the
implementations of their respective behavior.
12.
13. • This is what our new Cats class looks like.
• What we have effectively done is that a Cat
will now delegate its Purring and Eating
behaviour, instead of using Purring methods
defined in the Cat class (or subclasses).
14. public Class Cats
{
public IEat eat;
public IPurr meow;
.
public void ExecuteEat()
{
eat.Eat();
}
public void ExecutePurr()
{
meow.Purr();
}
}
Public Class Persian : Cats, IEat, IPurr
{
public Persian()
{
eat = new CanEat();
meow = new Whimper();
}
}
Public Class ToyCat : Cats, IEat, IPurr
{
public ToyCat()
{
eat = new CantEat();
}
}
15. Sample Client code
Public Static Void Main(String[] args….)
{
Cats c = new Persian();
c.ExecutePurr();
c.ExecuteEat();
}
16. Flexibility and Code Maintenance
• There is still room for flexibility
• We are doing a poor job of initializing the
instance variables in a flexible way
• Polymorphism : The PurrBehavior instance
variable is an interface type. Dynamically
assign a different PurrBehavior
implementation class at runtime or even from
the client without having to alter code.
17. • Let us make changes below to the Cat class.
We are introducing two methods
– SetPurrBehaviour(PurrBehaviour b)
– SetEatBehaviour(EatBehaviour e)
• From the client code now we can dynamically
add a new behaviour and without modifying
lots of code add extra functionality.
18. public Class Cats
{
public IEat eat;
public IPurr meow;
.
public void SetPurrBehaviour(IPurr b)
{
meow = b;
}
public void SetEatBehaviour(IEat e)
{
eat = e;
}
}
public class Hiss : IPurr
{
public void Purr()
{
// HISS HISS
}
}
19. Client Code looks like
• Static void main()
• {
– Cat p = new Persian();
– P. SetPurrBehaviour(new Hiss ());
– P.ExecutePurr();
• }
20. Welcome to the Strategy Pattern
• Patterns should be applied depending on the
need of the situation.
• Apply basic OOPS concepts first then refactor.
• Separate what changes
• Always code to an Interface
• Open for extension and closed for
modification
• Favor composition over inheritance.
Editor's Notes
We are asked to develop a simulation kind of application that the client wants to simulate whatever a Cat does. That is the client wants to have features such as walk, run, purr, jump, wag tail.
It is simple, just add a function called Eat() to the super class Cats and with the magic of inheritance all Cats will now Eat.
As requirements keep changing the above design will turn out to be a maintenance nightmare. For every class or entity that we add we might end up having lots of functions that will not have any implementation.
The result? Fewer unintended consequences from code changes and more flexibility in your systems
For instance, we might have one class that implements Purring, another that implements Eating, and another that implements silence.