marcelo santos – ooad-cdt309, spring 2008, ide-mdh 1 object-oriented analysis and design - cdt309...

36
Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Upload: silvester-wilkins

Post on 16-Dec-2015

215 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1

Object-Oriented Analysis and Design - CDT309

Period 4, Spring 2008

Open-closed principle

Page 2: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 2

Object connectivity

• Client classes use services from supplier classes:

• A module (class) is open when it’s available for extension (add, enlarge).

• A module is closed if it’s not subject to further change (it has a fixed number of functions).

Client Supplier<<use>>

Page 3: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 3

Advantages

• Closed module: can be used as a stable component in the system, avoiding changes that potentially affect the whole design

• Open module: make it possible to extend and modify the system in the awake of new capabilities and functionalities, keeping maintenace costs down

Page 4: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 4

Open-Closed Principle

• We should try to produce modules that are simultaneously open and closed.

This looks like a contradiction!

Page 5: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 5

General solution

• Distinguish between interface and implementation.– Implementation can be modified without

affecting clients.– How can we do this? What’s the interface?

Page 6: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 6

General solution

• The interface is the public definitions

public class Supplier {

private int attribute; public void operation() { // implementation of operation }}

Operation visible to the client

Page 7: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 7

General solution - advantages

• We can change the implementation of the operation in the supplier without the need to change the client

• We can add new operations and attributes also without the need to change any the client

• Is this a good solution?

Page 8: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 8

General solution - limitations

• In C++, modifications in the header (as if you want to add a private attribute in the Supplier) requires clients modules to be recompilated, even if the changes are invisible to them.– The open-closed principle should be language-

independent.

• Different clients of a module can use different subsets of the visible interface. – It is difficult to know exactly what changes to a

module will affect a given client.

• Can we have a better solution?

Page 9: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 9

Let’s use abstract classes

• New subclasses can be added, extending (or specializing) the AbstractSupplier or providing alternative implementation of the interface.

Page 10: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 10

Java’s code

public abstract class AbstractSupplier{ public abstract void operation();}

public class ConcreteSupplier extends AbstractSupplier { private int attribute; public void operation() { // implementation of operation }}

Page 11: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 11

Abstract classes

• Dependencies:

• The use of abstract classes is fundamental for working with design patterns.

Page 12: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 12

Abstract classes

What happens If we need to modify the interface of the AbstractSupplier due to changes on the needs of the client (like add a new operation)?

We need more principles…

Page 13: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 13

Principle: No Concrete SuperClass

• All Superclasses should be abstract. Only leaf classes should be concrete.

• Why? Let’s see an example…

Changes ahead: the bank wants to add a savings account. How would you do that?

A class to provide accounts in a bank.

Page 14: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 14

Easy solution:

The subclass inherits the shared functionalities

Concrete superclass

Page 15: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 15

Doing changes

• Now the bank decides to allow accounts become overdraw, but not on SavingsAccount’s.

How to do that?

Page 16: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 16

One possibility

public class CurrentAccount {...

void withdraw (double amt) { if (this.instanteof SavingsAccount) {

// check if becoming overdraw }

balance -= amt;}...

}What are possible problems with this solution?

Chech the type of the account

Page 17: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 17

Problems with extension

Public class CurrentAccount { void withdraw (double amt) { if (this.instanteof SavingsAccount) {

// check if becoming overdraw }

balance -= amt; }}

If there is a new subclass, changes on this code will be necessary:

the module is not closed.

The superclass is aware of the existence of subclasses!

Page 18: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 18

Problems with extension

void cashCheque (currentAccount a) { if (this.instanceof SavingsAccount) { return; } // cash cheque}

Adding new functionalities. For example: add cheques capabilities, but not on SavingsAccounts.

Could be like:

What is causing the problems?

Page 19: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 19

The cause of the problem

void cashCheque (currentAccount a) { if (this.instanceof SavingsAccount) { return; } // cash cheque}

• Role 1: as a superclass, this interface is implemented by all accounts objects and subclasses

• Role 2: it is also providing a default implementation

This superclass has two roles

Page 20: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 20

General solution

• All superclasses should be abstract.

Overrides with the code that check if becoming overdraw

Page 21: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 21

Coupled design

• Suppose you need to add a function to the interface due to new requirements.

• How can you do it without modifying the AbstractSupplier?

Page 22: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 22

Coupled design

• you have to modify the abstract supplier• maybe clients should be recompiled• this new function will have to be

implemented in all existing concrete supplier classes

• or a default implementation can be provided by the abstract supplier

• Suppose you need to add a function to the interface due to new requirements…

Page 23: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 23

Decoupling the Interface

• Instead of making abstract supplier as a class, make it as an interface. So, concrete providers are no longer subclasses of abstract supplier, but instead provide realizations of the interfaces.

How to do this?

Page 24: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 24

Making an interface

Page 25: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 25

Extending the interface

• Now we can extend the interface to provide a new operation:

Page 26: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 26

More Design Pattern

Factory Method Design Pattern

Page 27: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 27

Back to Duck’orama

… more ducks

… more quacks

… more flying types

We used the strategy pattern in the example

Page 28: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 28

Creating a new object

• How do you have the concret duck objects?...

Duck duck;

if (picnic) {

duck = new MallarDuck();} else if (hunting) ) { duck = new WildDuck();} else if (inBathTube) { duck = new RubberDuck();}...

The objects are created according to a context

Page 29: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 29

Problems

• You might have several places in the system where this kind of code for creating objects is repeated

• If you need to do a change…

...

Duck duck;

if (picnic) {

duck = new MallarDuck();} else if (hunting) ) { duck = new WildDuck();} else if (inBathTube) { duck = new RubberDuck();}duck.showBehaviour();...

Does this code follow the open-closed principle?

Page 30: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 30

Identifying what varies• We want to encapsulate the

code the object creation:

...

Duck duck;

?????

duck.showBehaviour();...

if (picnic) {

duck = new MallarDuck();} else if (hunting) ) { duck = new WildDuck();} else if (inBathTube) { duck = new RubberDuck();}

How can we do this?

Page 31: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 31

Simple solution

• Move the code to a new class:

public class DuckFactory {public Duck createDuck(DuckType t){

Duck duck = null;if (t == picnic) { duck = new MallarDuck();} else if (t == hunting) ) { duck = new WildDuck();} else if (t == inBathTube) { duck = new RubberDuck();}return duck;

}}

Page 32: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 32

Using the factory• Let’s have store of ducks:

public class DuckStore {DuckFactory df;public DuckStore(DuckFactory df){

this.df = df;}public Duck getDuck(DuckType t){

Duck duck;duck = df.createDuck(t);duck.showBehaviour();...return duck;

}...

}

The store has the factory to build the ducks.

Every time you need a new duck, you just get it from the store.

Page 33: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 33

Example

• Write the main program using the factory and the store of ducks.

public class DuckFactory {public Duck createDuck(DuckType t){

Duck duck = null;if (t == picnic) { duck = new MalarDuck();} else if (t == hunting) ) { duck = new WildDuck();} else if (t == inBathTube) { duck = new RubberDuck();}

return duck;}

}

public class DuckStore {DuckFactory df;public DuckStore(DuckFactory df){

this.df = df;}public Duck getDuck(DuckType t){

Duck duck;duck = df.createDuck(t);duck.showBehaviour();...return duck;

}...

}

Page 34: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 34

Adding new duck types

• Now it is much easier to inclue a new type of duck, and you only need to change one place: the factory.

• Draw the class diagram

StrangeDuck

CoiledDuck WersternDuck

USBDuck

Page 35: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 35

More changes

• Due to the huge success of the game, the company decided to develop a new game, the Duck Raider, with several types of strange ducks.

• How would you do?

• Can you reuse the code?

Page 36: Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 1 Object-Oriented Analysis and Design - CDT309 Period 4, Spring 2008 Open-closed principle

Marcelo Santos – OOAD-CDT309, Spring 2008, IDE-MdH 36

• Deriving the pattern in the whiteboard