Framhald af umfjöllun um hlutbundna forritun og hönnun. Nú förum við yfir Generic Programming sem sem leið til að búa til sveigjanlega og endurnýtanlegar einingar. Skoðum líka reflection. Þá verður farið fyrir hvernig má hann laustengdar einingar og notum við frægan andarleik sem dæmi.
Þá mun Code Horror Dude kíkja í heimsókn
5. Generic Programming
Programming in an data type independent way
– Same code is used regardless of the data type
Example
– Sort can be applied to any data type
– Generic collection
• Java Collection Framework
Design Principle
– Always use the most generic data type possible
6. Generic Programming
All classes extend Object
– Allows generic algorithms and data structures
static int find (Object[] a, Object key)
{
int i;
for (i=0;i<a.length;i++)
if (a[i].equals(key)) return i;
return -1;
}
Employee[] staff = new Employee[10];
Employee e1 = new Employee("Dilbert");
staff[x] = e1;
int n = find(staff, e1);
7. Generic Programming
Generic collections
– ArrayList is an example class that uses Object
ArrayList al = new ArrayList();
al.add (new Employee ("Dilbert"));
al.add (new Employee ("Wally"));
al.add (new Employee ("Alice"));
Iterator i = al.iterator();
Employee e;
while (i.hasNext())
{
e = (Employee)i.next();
System.out.println(e.getName());
}
Dilbert
Wally
Alice
8. Generic Programming
Generic collections
– The Collections class is another example
List<Employee> list = new ArrayList<Employee>();
list.add (new Employee ("Dilbert"));
list.add (new Employee ("Wally"));
list.add (new Employee ("Alice"));
Collections.sort(list);
for (Employee e: list)
{
System.out.println(e);
}
Alice
Dilbert
Wally
10. Reflection
Reflection allows examination and manipulation of
objects at runtime
– Get information about a class
• Fields, methods, constructors, and super classes
• Constants and method declarations belong to an interface
– Create an instance of a class whose name is not known
until runtime
– Get and set the value of an object's field, even if the field
name is unknown to your program until runtime
– Invoke a method on an object, even if the method is not
known until runtime
11. Reflection
static void showMethods(Object o)
{
Class c = o.getClass();
Method[] theMethods = c.getMethods();
for (int i = 0; i < theMethods.length; i++) {
String methodString = theMethods[i].getName();
System.out.println("Name: " + methodString);
String returnString = theMethods[i].getReturnType().getName();
System.out.println(" Return Type: " + returnString);
Class[] parameterTypes = theMethods[i].getParameterTypes();
System.out.print(" Parameter Types:");
for (int k = 0; k < parameterTypes.length; k ++)
{
String parameterString = parameterTypes[k].getName();
System.out.print(" " + parameterString);
}
System.out.println();
}
} }
12. Reflection
public class ReflectMethods
{
public static void main(String[] args)
{
Polygon p = new Polygon();
showMethods(p);
} Name: getBoundingBox
Bla
Return Type: java.awt.Rectangle
Parameter Types:
Name: contains
Return Type: boolean
Parameter Types: java.awt.geom.Point2D
...
Name: toString
Return Type: java.lang.String
Parameter Types:
13. Reflection
Reflection is very useful in frameworks
– Infrastructure code
– “plumbing” – The “Noise”
Examples
– Create Java objects from XML descriptions
– Load classes at runtime and invoke methods
– Tools and utilities for development
14. Dynamically Loading Classes
Classes can be dynamically loaded at runtime
– Offers the flexibility to decide which class to run
dynamically
– Class names can be specified in configuration files
Class class
Class instanceClass = Class.forName("RssFeedReader");
reader = (FeedReader)instanceClass.newInstance();
15. A) BD
B) DB
C) BDC
D) Compilation fails
QUIZ
class Top {
public Top(String s) {
System.out.print("B");
} }
public class Bottom2 extends Top {
public Bottom2(String s) {
System.out.print("D");
}
public static void main(String [] args) {
new Bottom2("C");
System.out.println(" ");
} }
16. A) BD
B) DB
C) BDC
D) Compilation fails
QUIZ
✔
class Top {
public Top(String s) {
System.out.print("B");
} }
public class Bottom2 extends Top {
public Bottom2(String s) {
System.out.print("D");
}
public static void main(String [] args) {
new Bottom2("C");
System.out.println(" ");
} }
18. Object Oriented Design
Design and implementation of software needs to
be of quality
– Badly designed, well implemented = problem!
– Well designed, badly implemented = problem!
CODE
HORROR!!
CODE HORROR DUDE
19. Object Oriented Design
Good design
Is based on OO principles
Abstracts complex APIs such as J2EE
Is flexible and can be changed
Contains loosely coupled components
24. Problem!
But not all duck fly – We forgot Rubber Duck!
25. How can we fix this?
Just override fly and quack to do nothing
26. We even think ahead
We fix all non-flyable and non-quackable ducks
as well
Code smell!
27. QUIZ
Which of the following are disadvantages of using inheritance to
provide Duck behavior?
A) Code is duplicated across subclasses
B) Runtime behavior changes are difficult
C) We can’t make ducks dance
D) Hard to gain knowledge of all duck behaviors
E) Ducks can’t fly and quack at the same time
F) Changes can unitentionally affect other ducks
✔
✔
✔
✔
28. The Problem
The problem is this
– Derived classes (RubberDuck) are forced to inherit
behaviour they don’t have
– Derived classes (RubberDuck) needs to be exposed
to the inner workings of the superclass (Duck)
– Users of the base class (Duck) should expect same
functionality
– Violation of the Liskov Substitution Principle
29. The Liskov Substitution Principle
Subtypes must be
substitutable for their base
types. Code that uses
references to base class must
be able to use objects of
derived classes without
knowing it.
Barbara
Liskov
30. The Liskov Substitution Principle
All code operating with reference to the base
class should be completely transparent to the
type of the inherited object
It should be possible to substitute an object of
one type with another within the same class
hierarchy
Inheriting classes should not perform any
actions that will invalidate the assumptions made
by the base class
31. LSP Example
public class Rectangle {
protected int _width;
protected int _height;
public int getWidth() {
return _width;
}
public int getHeight() {
return _height;
}
public void setWidth(int width) {
_width = width;
}
public void setHeight(int height) {
_height = height;
}
}
32. LSP Example
public class Square extends Rectangle {
public void setWidth(int width) {
_width = width;
_height = width;
}
public void setHeight(int height) {
_height = height;
_width = _height;
}
}
Implementation convenience
33. LSP Example
import junit.framework.Assert;
import org.junit.Test;
public class RectangleTests {
@Test
public void areaOfRectangle() {
Rectangle r = new Square();
r.setWidth(5);
r.setHeight(2);
// Will Fail - r is a square and sets
// width and height equal to each other.
Assert.assertEquals(r.getWidth() * r.getHeight(),10);
}
}
34. Trying to fix the Problem
Let’s try using interfaces
– Flyable and Quackable Code duplication!
35. What is the Problem?
We tried this
– Inheritance changes all subcasses
– Interfaces cause code duplication
The problem is we are mixing different types of
code in one type of classes
Fix
– Separate Variation Design Principle
– Take what varies and encapsulate it so it wont affect
the rest of the code
36. Separate Variations
Identify the aspects of
your application that
vary and separate
them from what stays the
same
37. Separation of Concerns
Separate what changes from what stays the
same
– Move duck behavior to a separte classes
FlyWithWings flyBehavior = new FlyWithWings();
DATA TYPE IS TOO SPECIFIC
38. Separation of Concerns
But the Duck classes cannot use the concrete
behavior classes!
– We need an interface or supertype
FlyBehavior flyBehavior = new FlyWithWings();
INTERFACE - POLYMORPHISIM
40. Loose Coupling with Interfaces
Advantages
– The ability to change the implementing class of any
application object without affecting calling code
– Total freedom in implementing interfaces
– The ability to provide simple test implementations and
stub implementations of application interfaces as
necessary
41. Program to an interfaces
Program to an implementation
Dog d = new Dog();
d.bark();
Program to interface/subtype
Animal animal = new Dog();
animal.makeSound();
Program to unknown creation
Animal animal = getAnimal();
animal.makeSound();
42. Program to an interfaces
Dependency Injection
– Make the caller responsible for setting the dependency
private Animal animal;
public setAnimal(Animal animal)
{
this.animal = animal;
}
...
animal.makeSound();
Injection happens
here, in the
set-method
LOOSE COUPLING = BEAUTIFUL!
44. Integrating the Behavior
The Duck classes will now delegate its flying
and quacking behavior
Behavior interfaces
Perform the
Bahavior
45. Integrating the Behavior
Using the behavior
public class Duck
{
QuackBehavior quackBehavior;
...
public void performQuack()
{
quackBehavior.performQuack()
}
}
We don’t care what kind of object this
is, all we care is that it knows how to
quack!
46. Integrating the Behavior
Setting the behavior
public class MallardDuck extends Duck
{
public MallardDuck()
{
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
}
This is not
programming
to an interface!
47. Setting Behavior Dynamically
Add two new methods to the Duck class
Dependency Injection
public void setFlyBehavior(FlyBehavior flyBehavior)
{
this.flyBehavior = flyBehavior
}
public void setQuackBehavior(QuackBehavior quackBehavior)
{
this.quackBehavior = quackBehavior
}
DuckFactory
{
public Duck getMallardDuck()
{
Duck duck = new MallardDuck()
duck.setFlyBehavior(new FlyWithWings());
duck.setQuackBehavior(new Quack());
return duck;
}
}
48. Setting Behavior Dynamically
The idea
– Don´t think: Mallard is-a flying duck, think: it has-a
flying behavior
– Putting two classes together where one is a member
in the other is a composition
Creating systems using composition give
flexibilty
– You can change the behavior at runtime
50. Object Composition
Problems with concrete inheritance
– Class hierarchy can get rigid
– Difficult to change the implementation
Object Composition is more flexible
– Allows the behaviour of an object to be altered at run
time, through delegating part of its behaviour to an
interface and allowing callers to set the
implementation of that interface
51. Summary
OO Programming is powerful
– If used correctly
– Remember Encapsulation, Interfaces, Polymorphism
Generic programming
– Using classes, abstract classes and interfaces can
lead to powerful and flexible programs
Reflection
– Powerful for building infrastructure
52. EXERCISE
Job interview question
You are given the assignment of creating a component that needs to
know sales statistics of Lottery tickets. You know that there is a
another component in the system, Sale Server, that handles the sale.
You need real-time information. What would you suggest?
53. Design Patterns
Design pattern is a general solution to a common
problem in software design
– Systematic approach for problems that reoccur in software
development
– Not complete solution but starting point for design
– Not code ready to use
– Patterns have names and definitions
– Built on common practices
Patterns should not be language dependant
– However patterns apply for types of programming
languages