design patters java_meetup_slideshare [compatibility mode]

61
20++ Years of Design Patterns Design Patterns Improve the Design of your Code Dr Dimitris Dranidis

Upload: dimitris-dranidis

Post on 24-Jan-2018

384 views

Category:

Software


2 download

TRANSCRIPT

20++ Years of

Design PatternsDesign Patterns

Improve the Design of your Code

Dr Dimitris Dranidis

Dr Dimitris Dranidis

� Senior Lecturer in Computer Science Department

� Programme director of the � MSc in Software Engineering & Telecommunications� MSc in Business, Management, Technology and Innovat ion

2

� MSc in Business, Management, Technology and Innovat ion

� Leader of the "Software Engineering & Service-Oriented Technologies " research group, r

� Research interests: � service-oriented computing, Cloud computing� model-based testing, formal methods, � software engineering education

� http://www.city.academic.gr/csd/dranidis/

Experience in Java/Design Patterns

� Teaching Design Patterns for >15 years � Advanced Software Development Techniques � MSc in Software Engineering and Telecommunications

� Principal Developer of JSXM� Model-based testing tool

� http:www.jsxm.org� 14 KLOC (JSXM core)� Plenty of Design Patterns applied

3

Outline

� Quiz problem� Bad smells in design� Open/Closed principle

4

� Open/Closed principle� Design Patterns� Examples of Design Patterns� Quiz solution� Key points

A PROBLEM TO KEEP YOU

BUSY!

5

Current Design (http://bit.ly/1zwNf4R)� Your current implementation of a class DocumentPrinter is as follows:

class DocumentPrinter {public void printDocument(Document doc) {

if (doc.getType().equals("PDF")) {PDFPrinter pdfprinter = new PDFPrinter();PDFPrinter pdfprinter = new PDFPrinter();pdfprinter.printPDF(doc.getContent());

}else if (doc.getType().equals("HTML")) {

HTMLPrinter htmlprinter = new HTMLPrinter();htmlprinter.printHTML(doc.getContent());

}else

throw new RuntimeException("Wrong type of document");}

}6

Constraints

� Library classes (These classes cannot be modified). � Document, PDFPrinter and HTMLPrinter

� You are expecting other types of documents to be � You are expecting other types of documents to be handled in the future and you would not like to change your DocumentPrinter class continuously.

� Change DocumentPrinter once and for all!� Make it open for extensions and closed to modifications !

7

What we wish to avoid:

class DocumentPrinter {public void printDocument(Document doc) {

if (doc.getType().equals("PDF")) {PDFPrinter pdfprinter = new PDFPrinter();pdfprinter.printPDF(doc.getContent());

}}else if (doc.getType().equals("HTML")) {

HTMLPrinter htmlprinter = new HTMLPrinter();htmlprinter.printHTML(doc.getContent());

}else if (doc.getType().equals(“XML")) {

XMLPrinter xmlprinter = new XMLPrinter();xmlprinter.printXML(doc.getContent());

}else

throw new RuntimeException("Wrong type of document");}

}

8

DESIGN SMELLS

9

Design smells

� Rigidity : Hard to change� A change forces many other unforeseen changes� “Changing it was a lot more complicated than I

thought”� Fragility : Easy to break

� A change forces the application to break in often � A change forces the application to break in often unforeseen ways

� Fragile modules: The more you fix them the worst they get

� Immobility : Hard to reuse� Useful parts are hard to separate

� Viscosity : Hard to do the right thing� Many ways to deal with change; hacks are easier than

design-preserving ways� Caused by the software or the environment

10

Design smells

� Needless complexity : Overdesign� Not useful (even unused) design

elements� Dealing with anticipated requirements

� Needless repetition : Cut & Paste abuse� Needless repetition : Cut & Paste abuse� Redundant code� Bugs require repetitive and different fixes

� Opacity : Difficult to understand� Easy when you write it, difficult when you

read it

11

OPEN-CLOSED PRINCIPLE

12

OCP: Open-Closed Principle

� A module should be � Open for extension� Closed for modification

� How can we extend the client so that it works with other servers (OPEN) without having to modify the client (CLOSED)?

Client Server

13

OCP: Abstraction is the key!

Client«interface»

ClientInterface

� Bertrand Meyer 97

Server

14

DESIGN PATTERNS

15

What are Design patterns?

� Well-known best design practices

Let’s apply a Factory � Named solutions to design

problems by experienced developers

� Vocabulary of principles to design software

Let’s apply a Factory and a Strategy!

16

A Pattern Language: Towns, Buildings, Construction (1977)

� Book on architecture, urban design, and community livability. � Patterns describe a problem

and then offer a solution. and then offer a solution.

� Still one of the best-selling books on architecture

17

Gang of Four (GoF) Design Patterns (1994)

� 23 patterns categorized in� Creational� Structural� Behavioral

18

Quotes from the Book

� Program to an interface, not an implementation

� Favor object composition over class inheritanceinheritance

� Inheritance breaks encapsulation� Implement abstract classes,

do not inherit concrete classes!

19

22 PLoP conferences (1994-today)

� Pattern Languages of Programs � Annual conferences� *PLoP� *PLoP

20

Patterns in core Java

� All patterns have been implemented in Java’s core libraries:� http://stackoverflow.com/questions/167

3841/examples-of-gof-design-patterns-3841/examples-of-gof-design-patterns-in-javas-core-libraries

� or google:� Examples of GoF Design Patterns in

Java

21

DESIGN PATTERNS

EXAMPLES

22

SHAPES EXAMPLE

23

Shapes example

public class Rectangle {private double width;private double height;

public Rectangle ( double w, double h ) {width = w ;height = h ;

}

public double getArea() { return width * height ; }}

24

Shapes example

public class AreaPrinter {private Rectangle shape;public AreaPrinter (Rectangle s ) { shape = s ; }public void printArea () {

System.out.println( "Shape area : " + shape.getArea() ) ;System.out.println( "Shape area : " + shape.getArea() ) ;}

}public class Main {

public static void main( String arg[] ) {Rectangle rectangle = new Rectangle(2.0, 5.0);AreaPrinter ap = new AreaPrinter( rectangle ) ;ap.printArea () ;

}}

25

Desired extensions

� We want our application to work with other types of shapes: Squares, Triangles, Circles, Polygons, etc.

public class Square {private double width;private double width;public Square ( double w ) {

width = w ;}public double getArea() { return width * width ; }

}� Do we need another AreaPrinter for Square?� Can we make AreaPrinter work for both Rectangle

and Square?

26

Abstraction is the key!

public interface Shape {public double getArea();

}

public class AreaPrinter {public class AreaPrinter {private Shape shape;public AreaPrinter ( Shape s ) { shape = s ; }public void printArea () {

System.out.println( "Shape area : " + shape.getArea() ) ;}

}

AreaPrinter is now open to extensions, closed to mod ifications!

27

Concrete classes implement the desired interfacepublic class Rectangle implements Shape {

private double width;private double height;public Rectangle ( double w, double h ) {

width = w ;height = h ;height = h ;

}public double getArea () { return width * height ; }

}public class Square implements Shape {

private double width;public Square ( double w ) {

width = w ;}public double getArea () { return width * width ; }

}28

Polygons?

� Polygons’ area is hard to calculate! We would not like to write the code ourselves.

� Luckily we find a class Polygon which offers the ca lculation of its objects’ area.� Source code not available OR� We don’t wish to change the implementation of Polyg on� We don’t wish to change the implementation of Polyg on

public class Polygon {...... public Polygon ( List points ) { .... }public double computeArea () { .... }......

}

� How can we integrate polygons into our Shapes application?29

Adapter Design Pattern

public class PolygonAdapter implements Shape {

private Polygon polygon; // composition

public PolygonAdapter (Polygon c ) {polygon = c ;

}

public double getArea () {return polygon.computeArea() ; // indirection

}}

30

Main client

public class Main {public static void main( String arg[] ) {

Rectangle rectangle = new Rectangle(2.0, 5.0);AreaPrinter ap = new AreaPrinter( rectangle ) ;ap.printArea () ;ap.printArea () ;Square square = new Square (3.0);AreaPrinter sp = new AreaPrinter( square ) ;sp.printArea () ;Polygon polygon = new Polygon (......);AreaPrinter pp = new AreaPrinter (

new PolygonAdapter(polygon));pp.printArea () ;

}}

31

Adapter (GoF, Structural Pattern)

� Intent� convert the interface of an existing class into another interface

used by clients� Motivation:

� want to use an existing class but ... � want to use an existing class but ... � interface of class is not compatible to the one you use and� modification of class is out of question because

� source code of class is not available or� it is a general-purpose class (you do not want to modify)

� resolve incompatible interfaces� provide a stable interface to similar classes with different

interfaces

32

Problem

Adaptee

+specificRequest()

<<interface>>

Target

+request()

Client

+specificRequest() +request()

incompatible interfaces

33

Adaptee

+specificRequest()

<<interface>>

Target

+request()

Client

Adapter Solution

+specificRequest()

specificRequest()

+request()

Adapter

+request()

34

Adapter Solution

:Adaptee :Adapter :Client

Target

specificRequest() 2:

request() 1:

35

EMPLOYEE EXAMPLE

36

Current design

public class Employee {private double salary ;public Employee (double s) {

salary = s ;}}

public double getPayAmount () {return salary ;

}}� Assume that some privileged employees receive doub le salary � Assume that employees can be promoted� How can we extend Employee to protect it from chang es?

37

2 possible solutions

� Sub-typing (Inheritance)

� Include a type attribute

38

Sub-typing solution (??)

public class Manager extends Employee {public double getPayAmount () {

return 2 * salary ;return 2 * salary ;}

}

39

Sub-typing solution does not work!

� Objects cannot dynamically change their type� An Employee object cannot be converted to a

Manager object

More points of variation create class explosion!� More points of variation create class explosion!� Different types of employees could have different

promotion eligibility criteria� Leading to a huge

inheritance hierarchy tree.

40

Type attribute solution (??)(Too smelly, violates OCP)public class Employee {

private int type ;private double salary ;public static final int ENGINEER = 1;public static final int MANAGER = 2;public static final int MANAGER = 2;public Employee (double s, int t ) { salary = s ; type = t ; }public double getPayAmount () {

if (type == Employee.ENGINEER)return salary;

if (type == Employee.MANAGER)return salary * 2;

return salary ;}

}41

Strategy Pattern solution

public interface PaymentStrategy {public double getPayAmount (Employee context);

}public class EngineerPaymentStrategy implements PaymentStrategy {

public double getPayAmount (Employee empl) {return empl.getSalary() ;

}} public class ManagerPaymentStrategy implements PaymentStrategy {

public double getPayAmount (Employee empl) {return empl.getSalary() * 2 ;

}} 42

Strategy Pattern solution

public class Employee {private PaymentStrategy paymentStrategy ; // compositionprivate double salary ;public Employee (double s, PaymentStrategy strategy) {

salary = s ; paymentStrategy = strategy ;}public double getSalary () {return salary ;}

public double getPayAmount () {return paymentStrategy.getPayAmount(this) ; // indirection

}}

43

Strategy (GoF: Behavioral)

� Intent� define a family of related algorithms, encapsulate each one, and

make them interchangeable by providing a common interface� algorithm may vary by object and also may vary over time

Motivation:� Motivation:� Many different algorithms exist for fulfilling a responsibility� You need different variants of an algorithm� An algorithm uses data that clients shouldn't know about� A class defines many behaviors, and these appear as multiple

switch statements in the classes operations� Many related classes differ only in their behavior

44

Strategy (GoF)

� Motivation (cont):�Separate the algorithms from the object which

is using them becauseis using them because� an object may decide to change the algorithm it uses� an object will get complex if you include all the code of the

algorithms� an object will have to use conditionals to decide which algorithm it

will use� each algorithm uses its own algorithm-specific data � it is difficult to add new algorithms if they are hard coded in the

object.

45

Strategy Solution

<<interface>> Strategy

Context

46

Strategy

+algorithmInterface( context : Context )

strategy.algorithmInterface(this)

ConcreteStrategyA

+algorithmInterface( context )

ConcreteStrategyB

+algorithmInterface( context )

+contextInterface()

KEY POINTS

47

When should you use patterns

� You have to add some new functionality and you find out that:

You need to copy and paste code� You need to copy and paste code� You need to hack the solution� Current design does not allow

easy fit of the new functionality

48

Protect your code from changes

� Identify the variation points� Isolate the variation points,

separate them from what is stable.� Encapsulate variations in a

method/class� method encapsulation

� Template method, Factory method

� class encapsulation� Strategy, Abstract Factory

49

When NOT to use Design Patterns

� Patterns introduce complexity� Simple problems require

simple solutions� Over-conformance to good � Over-conformance to good

design principles leads to “Needless Complexity ”

� Apply Design Patterns only when it is necessary!

� Remember: Not everything is a nail!

50

SOLUTION TO PROBLEM

51

Current Design (http://bit.ly/1zwNf4R)

class DocumentPrinter {public void printDocument(Document doc) {

if (doc.getType().equals("PDF")) {PDFPrinter pdfprinter = new PDFPrinter();pdfprinter.printPDF(doc.getContent());pdfprinter.printPDF(doc.getContent());

}else if (doc.getType().equals("HTML")) {

HTMLPrinter htmlprinter = new HTMLPrinter();htmlprinter.printHTML(doc.getContent());

}else

throw new RuntimeException("Wrong type of document");}

}

52

Analysis of the problem

� Variation points:�Objects created:

� PDFPrinter pdfprinter = new PDFPrinter();� PDFPrinter pdfprinter = new PDFPrinter();� HTMLPrinter htmlprinter = new HTMLPrinter();

� Interface of objects:� pdfprinter.printPDF(doc.getContent());� htmlprinter.printHTML(doc.getContent());

53

Adapter (Providing a stable interface)

public interface Printer {public void print (String content);

}public class PDFPrinterAdapter implements Printer {public class PDFPrinterAdapter implements Printer {

public void print (String content) {PDFPrinter pdfprinter = new PDFPrinter();pdfprinter.printPDF(content);

}}… similar for HTMLPrinterAdapter

54

Factory (GoF Creational)(Provides a stable interface for object creation)

public class PrinterFactory {Printer makePrinter (String doctype) {

if (doctype.equals("PDF")) {return new PDFPrinterAdapter();

}else if (doctype.equals("HTML")) {

return new HTMLPrinterAdapter()}else throw new RuntimeException("……");

}}

55

Singleton (GoF Creational)

public class PrinterFactory {

static PrinterFactory printerFactory = new PrinterF actory(); protected PrinterFactory() {}static PrinterFactory getInstance() { return printe rFactory; }

Printer makePrinter(String doctype) {….

}}

56

Final DocumentPrinter(Open for extensions, closed for modifications)

class DocumentPrinter {public void printDocument(Document doc) {

PrinterFactory printerFactory = PrinterFactory .getInstance();

Printer printer = printerFactory.makePrinter (doc.getType());printer.print (doc.getContent());

}}

57

… or as one-liner!

class DocumentPrinter {public void printDocument(Document doc) {

PrinterFactory .getInstance().makePrinter (doc.getType()). print (doc.getContent());print (doc.getContent());

}}

58

How to learn Design Patterns

� Pick a pattern and then find, and read as many examples as possible� Focus on the problems the patterns solves,

NOT the solution!NOT the solution!

� Invent your own examples/problems

� Apply the Design Pattern� … and enjoy!

59

How to apply Design Patterns

� Follow a problem-directed approach:� Identification of the pattern needed:

� understand the problem� find a pattern that addresses the problem (or a similar � find a pattern that addresses the problem (or a similar

problem)

� Study the Pattern solution� UML diagrams� code example (C++, Java, …)

� Apply the solution to the problem� embed pattern name in class/method names

60

Recommended Readings

� Design Patterns , GoF

� Refactoring , Martin Fowler

� Agile Software Development , Robert Martin

61