It started with a simple … A highly successful duck pond simulation game called SimUDuck The game can show a large variety of duck swimming and making.

Slides:



Advertisements
Similar presentations
Winter 2007ACS-3913 Ron McFadyen1 Duck Example Consider the text example (up to page 6). Each type of duck is a subclass of Duck Most subclasses implement.
Advertisements

+ Informatics 122 Software Design II Lecture 7 Emily Navarro Duplication of course material for any commercial purpose without the explicit written permission.
Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle.
D ESIGN P ATTERNS Introduction. C OURSE D ESCRIPTION Traditionally, OO designers have developed their own private "catalogs" of solutions to recurring.
Informatics 122 Software Design II
Strategy Pattern1 Design Patterns 1.Strategy Pattern How to design for flexibility?
Georgia Institute of Technology Workshop for CS-AP Teachers Chapter 3 Advanced Object-Oriented Concepts.
Inheritance Inheritance Reserved word protected Reserved word super
Slides 4/22 COP Topics Final Exam Review Final Exam The final exam is Friday, April 29 th at 10:00 AM in the usual room No notes, books, calculators,
The Bridge Pattern.. Intent Decouple an abstraction from its implementation so that the two can vary independently Also known as: Handle/Body.
SWE 4743 Strategy Patterns Richard Gesick. CSE Strategy Pattern the strategy pattern (also known as the policy pattern) is a software design.
Inheritance and object compatibility Object type compatibility An instance of a subclass can be used instead of an instance of the superclass, but not.
Informatics 122 Software Design II Lecture 5 Emily Navarro Duplication of course material for any commercial purpose without the explicit written permission.
Inheritance. Extending Classes It’s possible to create a class by using another as a starting point  i.e. Start with the original class then add methods,
1 Inheritance Reserved word protected Reserved word super Overriding methods Class Hierarchies Reading for this lecture: L&L 8.1 – 8.5.
Aalborg Media Lab 23-Jun-15 Inheritance Lecture 10 Chapter 8.
©The McGraw-Hill Companies, Inc. Permission required for reproduction or display. 4 th Ed Chapter N - 1 Chapter 13 Polymorphism is-a relationships Interfaces.
Design Patterns Module Name - Object Oriented Modeling By Archana Munnangi S R Kumar Utkarsh Batwal ( ) ( ) ( )
Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Design Patterns: someone has already.
Spring 2010ACS-3913 Ron McFadyen1 Duck Example Consider the text example (up to page 6). Each type of duck is a subclass of Duck Most subclasses implement.
Chapter 7 - Generalization/Specialization and Inheritance1 Chapter 7 Generalization/Specialization and Inheritance.
Object Oriented Software Development
COMP 121 Week 02. Agenda Review this week’s expected outcomesReview this week’s expected outcomes Review Guided Learning Activity solutionsReview Guided.
Design Patterns.
Chapter 1: Introduction to Design Patterns. SimUDuck Example.
CSC 142 O 1 CSC 142 Java More About Inheritance & Interfaces [Reading: chapter 13]
1 Unit 5 Design Patterns: Design by Abstraction. 2 What Are Design Patterns?  Design patterns are: Schematic descriptions of design solutions to recurring.
CS 210 Introduction to Design Patterns September 7 th, 2006.
1 Computer Science 340 Software Design & Testing Inheritance.
CS 210 Adapter Pattern October 19 th, Adapters in real life Page 236 – Head First Design Patterns.
The Strategy Pattern SE-2811 Dr. Mark L. Hornick 1 Class 1-2.
Object Oriented Software Development
SE-2811 Software Component Design Week 1, Day 2 (and 1-3 and 2-1) SE-2811 Dr. Josiah Yoder Slide style: Dr. Hornick 1.
Abstraction ADTs, Information Hiding and Encapsulation.
Object-Oriented Design and Programming (Java). 2 Topics Covered Today 2.3 Advanced Class Design –2.3.4 Design Patterns –2.3.5 Singleton Pattern –2.3.6.
Testing OO software. State Based Testing State machine: implementation-independent specification (model) of the dynamic behaviour of the system State:
CS 210 Final Review November 28, CS 210 Adapter Pattern.
The Strategy Pattern SE-2811 Dr. Mark L. Hornick 1.
CS 4240: Rethinking Some OOP Ideas and Terms for OOA&D Readings: Chap. 8 in Shalloway and Trott (referred to as S&T in these slides) Wikipedia on information.
Inheritance CSI 1101 Nour El Kadri. OOP  We have seen that object-oriented programming (OOP) helps organizing and maintaining large software systems.
CS 210 Introduction to Design Patterns August 29, 2006.
The Strategy Design Pattern © Allan C. Milne v
1 Inheritance Reserved word protected Reserved word super Overriding methods Class Hierarchies Reading for this lecture: L&L 9.1 – 9.4.
CS 210 Review October 3, 2006.
The Strategy Pattern (Behavioral) ©SoftMoore ConsultingSlide 1.
StarBuzz Coffee Recipe Boil some water Brew coffee in boiling water Pour coffee in cup Add sugar and milk Tea Recipe Boil some water Steep tea in boiling.
Inheritance ndex.html ndex.htmland “Java.
Author: DoanNX Time: 45’.  OOP concepts  OOP in Java.
IN 076 Pola Desain Perangkat Lunak Dosen: Hapnes Toba Oscar Karnalim
Duke CPS Programming Heuristics l Identify the aspects of your application that vary and separate them from what stays the same ä Take what varies.
STRATEGY PATTERN By Michelle Johnson. BACKGROUND Behavioral Pattern Allow you to define a family of algorithms, encapsulate each one, and make them interchangeable.
 Description of Inheritance  Base Class Object  Subclass, Subtype, and Substitutability  Forms of Inheritance  Modifiers and Inheritance  The Benefits.
CSCE 240 – Intro to Software Engineering Lecture 3.
SE 461 Software Patterns Welcome to Design Patterns.
Intro to Design Pattern
Object-Oriented Design
Strategy Design Pattern
Strategy Pattern.
Inheritance ITI1121 Nour El Kadri.
Behavioral Design Patterns
Strategy Design Pattern
Object Oriented Analysis and Design
SE-2811 Software Component Design
Object-Oriented Programming
SE-2811 Software Component Design
Java Inheritance.
Design pattern Lecture 9.
Strategy Design Pattern
Chapter 9 Carrano Chapter 10 Small Java
Software Design Lecture : 27.
Presentation transcript:

It started with a simple … A highly successful duck pond simulation game called SimUDuck The game can show a large variety of duck swimming and making quacking sounds

The initial design of the system Duck quack() swim() display() //other duck-like method RedheadDuck display() //looks like a redhead MallardDuck display() //looks like a mallard

But now we need the ducks to fly Duck quack() swim() display() //other duck-like method RedheadDuck display() //looks like a redhead MallardDuck display() //looks like a mallard

So we use OO inheritance Duck quack() swim() display() fly() //other duck-like method RedheadDuck display() //looks like a redhead MallardDuck display() //looks like a mallard Add fly() in super class

By putting fly() in super class Duck quack() swim() display() fly() //other duck-like method RedheadDuck display() //looks like a redhead MallardDuck display() //looks like a mallard We gave flying ability to ALL ducks, haha…

Including those that shouldn’t… Duck quack() swim() display() fly() //other duck-like method RedheadDuck display() //looks like a redhead MallardDuck display() //looks like a mallard RubberDuck quack(){ //overridden to Squeak} fly(){ ???} display() //looks like a rubberduck

No problem, a temporary fix!!! Duck quack() swim() display() fly() //other duck-like method RedheadDuck display() //looks like a redhead MallardDuck display() //looks like a mallard RubberDuck quack(){ //overridden to Squeak} fly(){ //overridden to do nothing} display() //looks like a rubberduck

Another temporary fix?? Duck quack() swim() display() fly() //other duck-like method RedheadDuck display() //looks like a redhead MallardDuck display() //looks like a mallard RubberDuck quack(){ //overridden to Squeak} fly(){ //overridden to do nothing} display() //looks like a rubberduck DecoyDuck quack(){ //overridden to mute} fly(){ //overridden to do nothing} display() //looks like a decoyduck

Something went wrong Having to override fly() to nothing for all those no- flying ducks The cause for this problem is when new duck features (flyable) are added to duck super class, we have some concrete ducks fly and some concrete ducks don’t some concrete ducks quack and some concrete ducks don’t Inheritance is not the right answer here

Here is our first try … Since flyable and quackable are not common behaviours of all ducks, we should take them out of the super class! Where to put them? Put them in separate interfaces Only use them when needed (i.e., for those ducks that fly, use the flyable interfaces, for those ducks who don’t, don’t use them)

How about an interface (Java and C++) Duck swim() display() //other duck-like method RedheadDuck quack(){ //implement} fly(){ //implement} display() //looks like a redhead MallardDuck quack(){ //implement} fly(){ //implement} display() //looks like a mallard RubberDuck quack(){ //implement to Squeak} display() //looks like a rubberduck 《 interface 》 Flyable fly() 《 interface 》 Quackable quack()

Oh, no! this time, something went horribly wrong … Implement similar fly() in all subclasses (duplicate code) Image what will happen if we want to make a small change to fly() This approach solves one problem (having to undo the method in superclass, i.e., no flying rubber duck anymore), but it destroys the code reuse (having to re- implement similar fly() in some subclass)

Pros and cons Not all inherited methods make sense for all subclasses – hence inheritance is not the right answer But by defining interfaces, every class that needs to support that interface needs to implement that functionality… destroys code reuse! So if you want to change the behavior defined by interfaces, every class that implements that behavior may potentially be impacted And….

Why this is happening? By adding the feature that some ducks can fly CHANGE, CHANGE,CHANGE When dealing with this change, inheritance is not the right answer Wishful thinking: Building software so that when we need to change it, we can do so with the least possible impact on the existing code.

Design Principle #1 Identify the aspects of the application that vary and separate them from what stays the same.

Applying Design Principle #1 Design Principle #1: Identify the aspects of the application that vary and separate them from what stays the same. In SimUDuck case Not change – display, swim (remain in Duck class) Change – fly, quack (pull out of Duck class ) Duck behaviours will live in a separate class

In the Duck simulation context… Duck Behaviors Parts that vary Parts that stay the same

Design Duck behaviors classes Keep things flexible, i.e., allow new behaviours added without changing existing code Only specify behavior when we have to, i.e., specify the flying feature of mallard duck when we initiate a mallard duck Change behaviors whenever we want dynamically, i.e., at runtime

Design Principle #2 Program to a super type (an interface), not a concrete implementation Animal makeSound() Cat makeSound(){ meow();} Meow(){//meow sound} Dog makeSound(){ Bark();} Bark(){//bark sound} super class Concrete Implementation

Polymorphism The declared type of the variables should be super type (interface or an abstract class) so that the objects assigned to those variable can be of any concrete implementation of the super type.

Example Animal makeSound() Cat makeSound(){ meow();} Meow(){//meow sound} Dog makeSound(){ Bark();} Bark(){//bark sound} super class Concrete Implementation

Programming to implementation Dog d = new Dog(); d.bark(); Or d.makeSound(); Programming to super type Animal d = new Dog(); d.makeSound(); Animal d = getAnimal(); d.makeSound(); Or even better (why?)

Example Animal makeSound() Cat makeSound(){ meow();} Meow(){//meow sound} Dog makeSound(){ Bark();} Bark(){//bark sound} super class Concrete Implementation

Applying Design Principle #2 Design Principle #2: Program to a supertype (an interface), not an implementation Duck behaviours are designed as two interfaces Then the implementation of each interfaces are given 《 interface 》 Flyable fly() 《 interface 》 Quackable quack()

How about an interface (Java and C++) Duck swim() display() //other duck-like method RedheadDuck quack(){ //implement} fly(){ //implement} display() //looks like a redhead MallardDuck quack(){ //implement} fly(){ //implement} display() //looks like a mallard RubberDuck quack(){ //implement to Squeak} display() //looks like a rubberduck 《 interface 》 Flyable fly() 《 interface 》 Quackable quack()

《 interface 》 Flyable fly() 《 interface 》 Quackable quack() FlyWithWings fly(){ //implement duck flying} FlyNoWay fly(){ // do nothing} Quack quack(){ //implement duck quacking} Squeak quack(){ //implement duck squeaking} Mute quack(){ //do nothing – can’t quack!}

Advantages Other types of duck can reuse of fly and quack behaviors (they are not hidden away in Duck) Add new behaviors without modifying existing code

How about an interface (Java and C++) Duck swim() display() //other duck-like method RedheadDuck quack(){ //implement} fly(){ //implement} display() //looks like a redhead MallardDuck quack(){ //implement} fly(){ //implement} display() //looks like a mallard RubberDuck quack(){ //implement to Squeak} display() //looks like a rubberduck 《 interface 》 Flyable fly() 《 interface 》 Quackable quack()

Integrating the duck behavior Key now is that Duck class will delegate its flying and quacking behavior instead of implementing these itself.

Integrating the Duck behaviours to super Duck class… Duck Behaviors Duck FlyBehavior: flyBehavior QuackBehavior: quackBehavior performQuack() swim() display() performFly() //other duck-like methods

Integrating the Duck behavior to super Duck class

Even better – setter functions Duck FlyBehavior flyBehavior QuackBehavior quackBehavior performFly() performQuack() swim() display() setFlyBehavior() setQuackBehavior() //other duck-like method change behaviors at runtime

Duck simulation recast using the new approach MallardDuck display() RedHeadDuck display() RubberDuck display() DecoyDuck display() Duck FlyBehavior: flyBehavior QuackBehavior: quackBehavior performQuack() performFly() setFlyBehavior() setQuackBehavior() swim() display() > FlyBehavior fly() FlyWithWings fly() // implements duck flying FlyNoWay fly() // do nothing – Can’t fly > QuackBehavior quack() Quack quack() // implements duck quacking Squeak quack() // implements squeak Mutequack quack() // do nothing IS-A (Inheritance) HAS-A (Composition)

How about an interface (Java and C++) Duck swim() display() //other duck-like method RedheadDuck quack(){ //implement} fly(){ //implement} display() //looks like a redhead MallardDuck quack(){ //implement} fly(){ //implement} display() //looks like a mallard RubberDuck quack(){ //implement to Squeak} display() //looks like a rubberduck 《 interface 》 Flyable fly() 《 interface 》 Quackable quack()

Design Principle #3 Favor composition over inheritance HAS-A can be better than IS-A Allows changing behavior at run time

Three Design Principles Identify the aspects of the application that vary and separate them from what stays the same. Program to a super type (an interface), not an implementation Favor composition over inheritance

Implementation is shared by all subclasses

《 interface 》 Flyable fly() FlyWithWings fly(){ //implement duck flying} FlyNoWay fly(){ // do nothing} FlyRocketPowered fly(){ // implement rocketed powered flying}

Duck simulation recast using the new approach MallardDuck display() RedHeadDuck display() RubberDuck display() DecoyDuck display() Duck FlyBehavior: flyBehavior QuackBehavior: quackBehavior performQuack() performFly() setFlyBehavior() setQuackBehavior() swim() display() > FlyBehavior fly() FlyWithWings fly() // implements duck flying FlyNoWay fly() // do nothing – Can’t fly > QuackBehavior quack() Quack quack() // implements duck quacking Squeak quack() // implements squeak Mutequack quack() // do nothing IS-A (Inheritance) HAS-A (Composition)

Strategy Pattern Define a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Character WeaponBehavior weapon; fight(); KnifeBehavior useWeapon() //implements cutting with // a knife BowAndArrowBehavior useWeapon() //implements fight with // bow and arrows AxeBehavior useWeapon() //implements fight with // an axe > WeaponBehavior useWeapon() Queen fight() King fight() Knight fight() Bishop fight() SpearBehavior useWeapon() //implements fight with // a spear setWeapon(WeaponBehavior w){ this.weapon = w; }

Character WeaponBehavior weapon; fight(); KnifeBehavior useWeapon() //implements cutting with // a knife BowAndArrowBehavior useWeapon() //implements fight with // bow and arrows AxeBehavior useWeapon() //implements fight with // an axe > WeaponBehavior useWeapon() Queen fight() King fight() Knight fight() Bishop fight() SpearBehavior useWeapon() //implements fight with // a spear setWeapon(WeaponBehavior w){ this.weapon = w; } Abstract

Character WeaponBehavior weapon; fight(); KnifeBehavior useWeapon() //implements cutting with // a knife BowAndArrowBehavior useWeapon() //implements fight with // bow and arrows AxeBehavior useWeapon() //implements fight with // an axe > WeaponBehavior useWeapon() Queen fight() King fight() Knight fight() Bishop fight() SpearBehavior useWeapon() //implements fight with // a spear setWeapon(WeaponBehavior w){ this.weapon = w; } Abstract Behavior Interface

Character WeaponBehavior weapon; fight(); KnifeBehavior useWeapon() //implements cutting with // a knife BowAndArrowBehavior useWeapon() //implements fight with // bow and arrows AxeBehavior useWeapon() //implements fight with // an axe > WeaponBehavior useWeapon() Queen fight() King fight() Knight fight() Bishop fight() SpearBehavior useWeapon() //implements fight with // a spear setWeapon(WeaponBehavior w){ this.weapon = w; } Abstract Behavior Interface

KnifeBehavior useWeapon() //implements cutting with // a knife BowAndArrowBehavior useWeapon() //implements fight with // bow and arrows AxeBehavior useWeapon() //implements fight with // an axe > WeaponBehavior useWeapon() Queen fight() King fight() Knight fight() Bishop fight() SpearBehavior useWeapon() //implements fight with // a spear Abstract Behavior Interface Character WeaponBehavior weapon; fight(); setWeapon(WeaponBehavior w){ this.weapon = w; }

The Open-Closed Principle (OCP) Software entities (classes, modules, functions, etc) should be open to extension, but closed for modification

Description Modules that conform to the OCP have two primary attributes: Open For Extension This means that the behavior of the module can be extended. That we can make the module behave in new and different ways as the requirements of the application change, or to meet the needs of new applications. Closed for Modification The source code of such a module is inviolate. No one is allowed to make source code changes to it.

Abstraction is the Key The abstractions are abstract base classes, and the unbounded group of possible behaviors is represented by all the possible derivative classes. Favor composition over inheritance

Strategy Pattern Define a family of algorithms, encapsulate each one, and make them interchangeable. It lets the algorithm vary independently from clients that use it. – [Gang Of Four] Moving the common code from detailed strategy class to its base abstract class Hiding complex detail information from client Client decides to use which strategy dynamically

Strategy Class Diagram Context ConcreteStrategyAConcreteStrategyBConcreteStrategyC > Strategy Interface

Implement the Strategy pattern Implement a Strategy interface for your strategy objects Implement ConcreteStrategy classes that implement the Strategy interface, as appropriate In your Context class, maintain a private reference to a Strategy object. In your Context class, implement public setter and getter methods for the Strategy object.

Context class class Context { IStrategy strategy; // Constructor public Context(IStrategy strategy) { this.strategy = strategy; } public void execute() { strategy.execute(); }

abstract strategy interface and concrete strategies interface IStrategy { void execute(); } // Implements the algorithm using the strategy interface class ConcreteStrategyA implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyA.execute()" ); } class ConcreteStrategyB implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyB.execute()" ); } class ConcreteStrategyC implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyC.execute()" ); }

Applications class MainApp { public static void main() { Context context; // Three contexts following different strategies context = new Context(new ConcreteStrategyA()); context.execute(); context = new Context(new ConcreteStrategyB()); context.execute(); context = new Context(new ConcreteStrategyC()); context.execute(); }

Layout Manager Sample Container -layoutManager :LayoutManager +Container(LayoutManager) +setLayoutManager( LayoutManager):void FormLayoutGridLayoutSelfDefined > LayoutManager

Input Validation Sample Context UserGroupA +validate:void UserGroupB +validate:void UserGroupC +validate:void > InputValidationStrategy +validate:void

Swing border example You can draw borders around almost all Swing components. Swing provides numerous border types for its components: bevel, etched, line, titled, and even compound. JComponent class acts as the base class for all Swing components which implements functionality common to all Swing components. JComponent implements paintBorder(), a method for painting borders around components.

The wrong way class JComponent { … protected void paintBorder(Graphics g) { switch(getBorderType()) { case LINE_BORDER: paintLineBorder(g); break; case ETCHED_BORDER: paintEtchedBorder(g); break; case TITLED_BORDER: paintTitledBorder(g); break;... } … }

The right way class JComponent { … private Border border; public void setBorder(Border border) { Border oldBorder = this.border; this.border = border; } public Border getBorder() { return border; } protected void paintBorder(Graphics g) { Border border = getBorder(); if (border != null) { border.paintBorder(this, g, 0, 0, getWidth(), getHeight()); } … }