Anda di halaman 1dari 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 thed 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; a StudyBehavior studyB; ... public void performResult(){ resultB.result(); } public void performStudy(){ 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(); } ... }

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; } 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 independeantly 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. implements the algorithm using the Strategy interface. is configured with a ConcreteStrategy object maintains a reference to a Strategy object may define an interface that lets Strategy acces its data.

ConcreteStrategy: Context:

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.

Anda mungkin juga menyukai