0% found this document useful (0 votes)
23 views

Design Patterns 1: Requested Change

The document discusses the strategy design pattern and how it can be applied to a course management system to allow behaviors like computing results and studying to vary independently of classes like specific course types. It provides an example implementation using interfaces to encapsulate behaviors and allow assigning specific strategy implementations at runtime or through subclassing.

Uploaded by

Aneta Şuletea
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views

Design Patterns 1: Requested Change

The document discusses the strategy design pattern and how it can be applied to a course management system to allow behaviors like computing results and studying to vary independently of classes like specific course types. It provides an example implementation using interfaces to encapsulate behaviors and allow assigning specific strategy implementations at runtime or through subclassing.

Uploaded by

Aneta Şuletea
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

DESIGN PATTERNS 1

Suppose we have the structure:

Requested change: We want to add new behavior representing:

1. computing results
2. study for the exam.

Solution: Add 2 new methods that implement the 2 behaviors, in the superclass.

Problems arrised:
− not all teachers compute the result with the same formula;
− Sports is facultative and have no result;
− there are different ways to study for SwEng and English; also Sports needs no computer
assisted study.

Solution: Override study() and result() in each subclass.


Subclasses of the base class (Course) override these methods in the base class.

General problem: Client will periodically request changes in the behavior of a product.
Solution: Use interfaces.
The operations result() and study() from Course where transferred to interfaces Result
and Study respectively.

Problems:
− code structure is disrupted;
− behavior is still implemeted in subclasses.

Fact: CHANGE is a software development constant.


Aim: To organise applications so that changes to code to be localized in order to be realized with
minimum impact on the rest of the code.

For that, we appeal to GOOD OO DESIGN PRACTICES.

P1 (GOOD OO DESIGN PRACTICE 1): Identify the aspects of the application that vary and separate them
from what stays the same.

Result of applying P1:


− fewer unintended consequences from code changes;
− more flexibility in the system;
− Sistem is structured into independently varying parts.

Procedure:
− take the parts that vary;
− encapsulate them;
− independently alter and/or extend them later.

Method (to separate changing behaviors):


− pull correspondent methods out of the base class;
− create a new set of classes to represent each behavior.

Applying P1 to our example: separate result() and study() operations in 2 classes, Result
and Study, that contain all needed implementations.

Subclasses of Course can instantiate objects of type Result and Study, on which to call
correspondent methods. We say the Course delegates behavior to Result and Study classes.
Obs. The base class (Course) is still a superclass for SwEng, English, Sports (and other
possible subclasses).

For more flexibility: how to allow changing behaviors dynamically.

P2 (GOOD OO DESIGN PRACTICE 2): Program to an interface (more generally: to a supertype), not to an
implementation.

Use a supertype to represent each behavior; supertypes expose behaviors as interfaces or


abstract methods.
Use its implementations that take responsibility for each particular behavior.

Advantages:
- other types of objects can reuse these behaviors
- new behaviors can be added without affecting:
- any existing behavior
- any class that use existing behavior

Applying P2 to our example: consider interfaces Result and Study which represent changing
behaviors. Specific implementations from SwEngResult, EnglResult, SwEngStudy and
EnglStudy are used at runtime based on polymorphism.
Recommendations:
1. Principles and patterns can be applied at any stage of the development lifecycle.
2. Keep commonalities in a base superclass (does not need to be an interface). The base
superclass delegates changing behavior to specific interfaces.

IMPLEMENTATION:
a. In the base class add instance variables declared of interface behavior type.
b. Remove from the base class and its subclasses all methods associated previously with the
considered behavior.
c. In the base class add methods that perform behavior.
d. To set statically the behaviors: set values for behavior instance variables in subclasses
constructors.
e. To set dynamically the behaviors: set values for behavior instance variables in a dedicated
method in subclasses.

public class Course {


ResultBehavior resultB;
StudyBehavior studyB; a
...
public void performResult(){
resultB.result();
}
public void performStudy(){
c
studyB.study()
}
...
}

Class Course delegates specific behavior to the objects referenced by resultB and studyB
instance variables.

To set statically the behaviors:

public class SwEng extends Course {


...
public SwEng(){
resultB = new SwEngResult();
studyB = new SwEngStudy(); d
}
...
}

The instance variables resultB and studyB are inherited from Course.
The method performResult() inherited from Course will realize, by polymorphism, the
behavior implemented in SwEngResult.

public class SwEngResult implements ResultBehavior {


...
public result(){
// implementation of an algorithm for computing the result
// specific to Software Engineering
}
}

For testing we will use the following class:

public class Test_static {


public static void main(String[] args){
Course c1 = new SwEng();
c1.performStudy();
c1.performResult();
...
}
}

To set dynamically the behaviors:

- add setter methods for resultB and studyB instance variables in the base class:

public class Course {


ResultBehavior resultB;
StudyBehavior studyB;
...
public void setStudyBehavior(StudyBehavior sb){
studyB = sb;
} e
public void setResultBehavior(StudyBehavior sb){
resultB = rb;
}

public void performResult(){


resultB.result();
}
public void performStudy(){
studyB.study()
}
...
}

- use inherited setter methods in each subclass to set behavior dynamically.

For testing:

- we suppose that a new way to compute results for Software Engineering is added, implemented
in:

public class SwEngNewResult implements ResultBehavior {


...
public result(){
// implementation of a new algorithm for computing the result
// specific to Software Engineering
}
}

- will use the following class:

public class Test_d {


public static void main(String[] args){
Course c1 = new SwEng();
c1.performStudy();
c1.performResult();
// change behavior at runtime by calling the inherited setter method
c1.setResultBehavior(new SwEngNewResult());
c1.performResult();
...
}
}
The previous example is illustrative for STRATEGY design pattern.

Excerpt from catalogue definition:

Name:
STRATEGY (POLICY)
Intent:
Design a family of algorithms, encapsulate each one, and make them interchangeable.
STRATEGY lets the algorithm vary independently from clients that use it.
Structure:

Participants:
Strategy:
- declares an interface common to all supported algorithms;
- Context uses this interface to call the algorithm defined by a ConcreteStrategy.
ConcreteStrategy:
- implements the algorithm using the Strategy interface.
Context:
- is configured with a ConcreteStrategy object
- maintains a reference to a Strategy object
- may define an interface that lets Strategy acces its data.

Aplicability when:
- many related classes differ only in their behavior - Strategy provides a way to configure a
class with one of many behaviors.
- you need different variants of an algorithm - Strategy can be used when these variants are
implemented as a class hierarchy of algorithms.
- an algorithm uses data that clients should not know about – Strategy is used to avoid
exposing complex, algorithm-specific data structures.
- a class defines many behaviors, and these appear as multiple conditional statements in its
operations – instead of many conditionals, move related conditional branches into their own
Strategy class.

You might also like