design patters java_meetup_slideshare [compatibility mode]
Post on 24-Jan-2018
384 Views
Preview:
TRANSCRIPT
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
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
� 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
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
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
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
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
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()
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
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
top related