This document discusses anti-object oriented design patterns that fight against constraints imposed by pure object-oriented programming languages like Java. It provides examples of the singleton, strategy, visitor, and other patterns, and how they work against OOP principles to provide functionality not directly supported by the language. The document argues that design patterns are useful for solving problems not addressed by the language, and that both patterns and languages can be improved by learning from their limitations.
2. Design Patterns
What’s a design pattern?
“A
general
reusable
solu-on
to
a
commonly
occurring
problem
within
a
given
context
in
so8ware
design”,
Wikipedia
DEVCON
2013
7. Problems caused by the language
We want to represent IPv4 addresses in our Java
program. Suggestions?
class IpV4Address {
private uint bits = 0;
public static IpV4Address fromCidr(String cidr) {
...
}
public bool isInSameNetwork(IpV4Address addr, Netmask netmask) {
...
}
...
};
DEVCON
2013
8. Problems caused by the language
We want to represent IPv4 addresses in our
program. Suggestions?
class IpV4Address {
private uint bits = 0;
public static IpV4Address fromCidr(String cidr) {
...
}
public bool isInSameNetwork(IpV4Address addr, Netmask netmask) {
...
}
...
};
DEVCON
2013
9. Problems caused by the language
Let
me
introduce
the
An@-‐
Object
Oriented
Design
PaGerns
DEVCON
2013
11. Singleton Pattern
public class Application extends Configurable {
private static Application instance;
OOP establishes some constraints:
ü Every object is bounded to a}lifecycle
private Application() { ...
ü Every classstaticas many instances as fit into
has Application getInstance() {
public
if
memory (instance == null)
instance = new Application();
return instance;
}
// The functionality of the application goes here
...
Singleton is fighting against these rules!
}
DEVCON
2013
12. Singleton Pattern
What if we bend the rules? ...
object Application extends Configurable {
// The functionality of the application goes here
...
}
DEVCON
2013
14. Strategy and Co.
interface Player {
void attack(Player enemy);
// Other stuff the player does
...
}
interface Weapon {
void attack(Player enemy);
}
ü Java is a pure-OOP programming
language
ü Everything is modeled using
objects
class AbstractPlayer implements Player {
private Weapon weapon;
public setWeapon(Weapon weapon) {
this.weapon = weapon;
}
public void attack(Player enemy) {
weapon.attack(enemy);
}
}
class Axe implements Weapon { ... }
class Sword implements Weapon { ... }
class Bow implements Weapon { ... }
DEVCON
2013
Strategy is fighting against the lack
of other mechanism to represent
behavior!
15. Strategy and Co.
What if we have a non-pure OOP language?
class player {
public:
typedef std::function<void(Player&)> weapon;
void set_weapon(weapon& w) { _weapon = w; }
void attack(player& enemy) {
_weapon(enemy);
}
private:
weapon _weapon;
};
void axe(player& enemy) { ... }
void sword(player& enemy) { ... }
void bow(player& enemy) { ... }
DEVCON
2013
16. Strategy and Co.
The lack of functions is not a matter exclusive for strategy
pattern
ü Observer pattern
ü Factory (method) pattern
ü Adapter pattern
ü …
DEVCON
2013
18. Visitor
interface CarElementVisitor {
void visit(Wheel wheel);
void visit(Engine engine);
void visit(Body body);
void visit(Car car);
}
interface CarElement {
void accept(CarElementVisitor visitor);
}
class Wheel implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Engine implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Body implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
DEVCON
2013
class Car implements CarElement {
public void accept(CarElementVisitor visitor) {
for(CarElement elem : elements)
elem.accept(visitor);
visitor.visit(this);
}
}
class Mechanic implements CarElementVisitor {
public void visit(Wheel wheel) { ... }
public void visit(Engine engine) { ... }
public void visit(Body body) { ... }
public void visit(Car car) { ... }
}
19. Visitor
Why not simply…?
interface CarElementVisitor {
void visit(Wheel wheel);
void visit(Engine engine);
void visit(Body body);
void visit(Car car);
}
class Car implements CarElement {
public void accept(CarElementVisitor visitor) {
for(CarElement elem : elements)
visitor.visit(elem);
visitor.visit(this);
}
elem is a
}
CarElement, and
visit(CarElement)
DEVCON
2013
is not defined in
visitor!
20. Visitor
Call visit(Wheel w)
interface CarElement {
void accept(CarElementVisitor visitor);
}
class Wheel implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Engine implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
visit(Engine
Call
class Body implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
Call visit(Body b)
DEVCON
2013
That’s why we need to
redefine accept() again
and again
e)
21. Visitor
What if we dispatch the message based on…
ü The receiver of the message, and…
ü The arguments of the message?
Let me introduce the double dispatch!
Visitor pattern is there to provide double dispatch
semantics not supported by the language
DEVCON
2013
23. Conclusions
ü Design patterns are bad
ü NOOOOOOOOOOO!!!!!!!
ü Design patterns are useful, even when they fight against the
language
ü We must learn from our errors and languages must evolve to
avoid them
And some opinions
ü OOP as implemented by Java is almost over
ü Learn Scala
DEVCON
2013