Software Design Patterns
Florian Rappl, Fakultät für Physik, Universität Regensburg
Software Design Patterns
Introduction to modern software architecture
Basics
What is OOP?
- OOP is a different way of thinking in programming
- Instead of having only functions that modify data we have objects that carry data
- These objects also have associated functions (then called methods)
- Advantage: Clear separation possible
- Such objects are usually so called instances of classes
- Objects are described by the data they carry (which are called fields)
OOP Overview
Structure Vs Class
- Creating own data types is mostly based on either structures or classes
- Structures should be used for immutable, primitive, i.e. small and atomic, types
- Classes should be seen as complex, i.e. compound, types that are build from other types
- Some languages impose restrictions and behavior depending on which kind is chosen (mostly managed languages)
- In this lecture we will exclusively use classes
Features
- Encapsulation enforces modularity
- Inheritance creates groups of similar objects and makes classes re-usable
- Polymorphism lets specializations implement their own behavior
- Decoupling makes code highly testable, exchangeable and general
OOP languages
- Simula (1967) initiated the idea
- OOP became popular with Smalltalk (mostly due to GUI)
- In the 80s Ada and Prolog followed
- Also C++ and Objective-C were introduced
- With Java the ideas of IL, managed code and OOP merged
- Finally C# took the ideas of Java even further
Language distinctions
- Some languages are pure: Eiffel, Scala, Smalltalk, Self, ...
- Others are focused on OOP (they still have procedural elements): Delphi, C++, C#, Java, Python, JavaScript, ...
- Some are derived from procedural ancestors: Pascal, VB (from Basic), Fortran, Perl, PHP, COBOL, ...
- There are also object-based languages, i.e. they support data types but not all OO features (like Modula-2)
- We will focus on C++, C# and Java
Hello World
using System;
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("Hello, World!");
}
}
import System;
public class Program {
public static void main(String[] args) {
out.println("Hello, World!");
}
}
#include <iostream>
using namespace std;
class Program {
public:
void Hello() {
cout << "Hello, World!";
}
};
int main(int argc, char **argv) {
Program *p = new Program();
p->Hello();
delete p;
return 0;
}
Basics of C#
class
creates a classstatic
marks methods as being instance independentusing
imports types from namespacespublic
sets members as being visible outside of the classprivate
members are accessible from the outside- Primitive types like in C (
int
,char
,double
, ...)
Basics of Java
- Overall quite similar to C#
- Inheritance is done by a keyword (
extends
) and not an operator (:
) - Differentiates in inheritance kind by a keyword (
implements
) - Types are imported with the
import
keyword - The
protected
modifier is likeprivate
, but lets derived classes access the members
Basics of C++
- We have to take care of the memory
- Classes should always be created with
new
- Accessing member variables of objects is then done by
->
, as opposed to the.
in other languages - Freeing objects can be achieved by calling
delete
(beware of arrays!) - Modifiers do not have to be set explicitly, but for blocks
- Header files have to be included as well
Constructors
- These are functions that are called implicitly after allocating memory
- Special form: No return value and same name as the class
- They can be used for doing initialization or checking on conditions
- They could throw exceptions
- We can specify arguments to impose dependencies
- Constructors also have a modifier, i.e. they could be restricted to be accessed from derived class constructors or only within the same class
- This can result in a very handy pattern: the so called Singleton pattern
Polymorphism
- Classes allow us to implement a method and re-implement the same method in a derived class
- This feature is called polymorphism
- The idea is that even though one talks to a more general kind of type (not knowing the specialized one) one accesses the special method
- The method is selected by a method selection algorithm
- This is either done at compile-time (special overload, C++) or at run-time (virtual method dispatch over a function table)
Polymorphism example
public class Shape
{
public virtual void Draw()
{
Console.WriteLine("Base draw");
}
}
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}
class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a rectangle");
}
}
public class Shape {
public void draw() {
System.out.println("Base draw");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
class Shape {
public:
virtual void Draw() {
cout << "Base draw";
}
};
class Circle : public Shape {
public:
void Draw() {
cout << "Drawing a circle";
}
};
class Rectangle : public Shape {
public:
void Draw() {
cout << "Drawing a rectangle";
}
};
Language implementation
- In Java every method is
virtual
, except those which are markedfinal
(cannot be overridden or hidden) - C++ does not require placing an
override
keyword - The
@Override
annotation in Java prevents typing mistakes (it is not required, but strongly recommended) - In C# the
override
is required, even though the method has been marked asvirtual
Abstract
- Previously we have seen a way to re-implement methods
- Additionally we can enforce implementation
- An abstract method is such a method that is required to be re-implemented
- Abstract classes are classes that can never be instantiated
- These two concepts build the foundation of many patterns
Abstract example
public abstract class Ball
{
public abstract int Hit(int speed);
}
public class BaseBall : Ball
{
public override int Hit(int batSpeed)
{
//Implementation
}
}
public abstract class Ball {
public abstract int hit(int speed);
}
public class BaseBall extends Ball {
@Override
public int hit(int batSpeed) {
//Implementation
}
}
class Ball {
public:
virtual int Hit(int speed) = 0;
};
class BaseBall : public Ball {
public:
int Hit(int batSpeed) {
//Implementation
}
};
Abstract usage
- C++ does not have special keywords
- Any class having abstract methods is abstract
- Abstract classes have to be marked as such in C# or Java
- It is not possible to create instances of abstract classes
- Abstract classes are useful to group something which has at least one method, which requires different implementation
Interfaces
- A step further than abstract classes are interfaces
- An interface is like an abstract class without any code
- It could be seen as a contract (sets up what kind of methods should be available)
- In modern software development interfaces are crucial
- Goal: Reduce dependencies and decouple classes
Interfaces in practice
interface IShooter
{
int Ammo { get; set; }
void ShootAt(int x, int y);
}
class Player : IShooter
{
/* Implementations */
}
interface Shooter {
void setAmmo(int value);
int getAmmo();
void shootAt(int x, int y);
}
class Player implements Shooter {
/* Implementations */
}
class Shooter {
public:
virtual void SetAmmo(int value) = 0;
virtual int GetAmmo() = 0;
virtual void ShootAt(int x, int y) = 0;
}
class Player : public Shooter {
/* Implementations */
}
Worth noting ...
- C# offers special constructs called properties (otherwise we prefer to use the so-called bean convention)
- In C++ interface-like types can be created by abstract classes that contain only abstract methods marked as
public
- Java requires a different keyword for implementing interfaces (however, for us this is educational)
- In C# and Java methods in interfaces have implicitly a
public
modifier
Comparison
C# | Java | C++ |
---|---|---|
Managed | Managed | Native |
Pointers possible | No pointers | Pointers required |
High OO | High OO | Low OO |
With Mono | Cross platform | With Qt |
C# 5 | Java 7 | C++11 |
Lambdas | Proxy | Lambdas |
Events | Custom | Custom |
The diamond problem
- C++ allows multiple inheritance, plus merging again
- Here we can build a diamond structure with a base class A, two subclasses B and C and a class D, that inherits from B and C
- Problem: We now have the methods have A duplicated
- Also the data of A is duplicated
- Solution: Instead of doing a normal inheritance, do a
virtual
one
Diamond hierarchy
A look at the creators
C#
Hejlsberg
Java
Gosling
C++
Stroustrup
Other languages
- Objective-C is an OO language that is empowering iOS and OSX applications
- Vala is using a lot of C# and D concepts to create native code
- Eiffel is build upon design by contract and is enforces OO principles
- JavaScript is a fully OO scripting languages, however, it is prototype-based and not class-based
- Visual Basic is a popular extension of Basic with OO in mind
- Functional OO languages like F#, Scala and others mix concepts
Design patterns
- A general reusable solution to a commonly occurring problem
- The context for the problem (and solution) is software
- Since it is a pattern it can be transformed to apply to our problem
- They usually follow best practices, even though the implementation might not
- Languages might enhance using these patterns
- Sometimes languages already provide integrations, which should be preferred
Literature
- Drayton, Peter; Albahari, Ben; Neward, Ted (2002). C# Language Pocket Reference.
- Gosling, James; Joy, Bill; Steele, Guy L., Jr.; Bracha, Gilad (2005). The Java Language Specification.
- Alexandrescu, Andrei; Sutter, Herb (2004). C++ Design and Coding Standards: Rules and Guidelines for Writing Programs.
- Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1995). Design Patterns: Elements of Reusable Object Oriented Software.