Design patterns are names given to object-oriented coding idioms. They are great because they facilitate communication. Unfortunately, most descriptions use UML pictures surrounded by pompous text and big examples.
When I say ..., I mean code that looks like ..., sort of.
Abstract factory:
interface Thing {}
interface Factory { Thing mk(/*...*/); }
interface Factory { Thing mk(/*...*/); }
Factory method:
interface Thing {}
abstract class Base {
abstract Thing mk(/*...*/);
/* do stuff */
}
abstract class Base {
abstract Thing mk(/*...*/);
/* do stuff */
}
Builder:
class Thing {/*...*/}
interface Builder {
void mkNew();
void buildPartA(/*...*/);
/*...*/
void buidPartZ(/*...*/);
Thing getResult();
}
interface Builder {
void mkNew();
void buildPartA(/*...*/);
/*...*/
void buidPartZ(/*...*/);
Thing getResult();
}
Lazy factory / Flyweight:
class Thing {
private static final Map<String,Thing> inst = new HashMap<String,Thing>();
private Thing(String args) {/*initialize from args*/}
public static get(String args) {
Thing t = inst.get(args);
if (t == null) {
t = new Thing(args);
inst.put(args, t);
}
return t;
}
}
private static final Map<String,Thing> inst = new HashMap<String,Thing>();
private Thing(String args) {/*initialize from args*/}
public static get(String args) {
Thing t = inst.get(args);
if (t == null) {
t = new Thing(args);
inst.put(args, t);
}
return t;
}
}
Prototype:
interface Prototype<T> { T clone(); }
class Thing implements Prototype<Thing> {/*...*/}
class Thing implements Prototype<Thing> {/*...*/}
Singleton:
class Thing {
private static inst = null;
private Thing() {/*...*/}
public Thing inst() {
if (inst == null) inst = new Thing();
return inst;
}
}
private static inst = null;
private Thing() {/*...*/}
public Thing inst() {
if (inst == null) inst = new Thing();
return inst;
}
}
Adapter:
interface Interface { void doA(); /*...*/ }
class Adaptee {/*...*/}
class Adapter extends Interface {
private Adaptee adaptee;
@Override public void doA() {
/* do stuff, most of the work being delegated to adaptee */
}
/*...*/
}
class Adaptee {/*...*/}
class Adapter extends Interface {
private Adaptee adaptee;
@Override public void doA() {
/* do stuff, most of the work being delegated to adaptee */
}
/*...*/
}
Bridge:
interface LowLevel { /*...*/ }
interface HighLevel { void doit(); /*...*/ }
class HlImpl implements HighLevel {
private LowLevel ll;
public HlImpl(LowLevel ll, /*...*/) {
this.ll = ll;
/*...*/
}
@Override void doit() { /* do work, using a lot methods in ll */ }
/*...*/
}
interface HighLevel { void doit(); /*...*/ }
class HlImpl implements HighLevel {
private LowLevel ll;
public HlImpl(LowLevel ll, /*...*/) {
this.ll = ll;
/*...*/
}
@Override void doit() { /* do work, using a lot methods in ll */ }
/*...*/
}
Composite:
interface Composite { Composite get(int index); }
Decorator:
interface Thing { void doit(); /*...*/ }
abstract class Decorator implements Thing {
protected Decorator wrapped;
}
class DecoratorA extends Decorator {
public DecoratorA(Decorator d) { this.wrapped = wrapped; }
@Override void doit() {
/* do extra stuff */
if (wrapped != null) wrapped.doit();
}
}
abstract class Decorator implements Thing {
protected Decorator wrapped;
}
class DecoratorA extends Decorator {
public DecoratorA(Decorator d) { this.wrapped = wrapped; }
@Override void doit() {
/* do extra stuff */
if (wrapped != null) wrapped.doit();
}
}
Facade:
package p;
/* The operations doX use various classes in the package p,
* are fairly high-level, and easy to understand by someone
* not very familiar with p.
*/
class Facade {
public void doA() {/*...*/}
public void doB() {/*...*/}
/*...*/
}
/* The operations doX use various classes in the package p,
* are fairly high-level, and easy to understand by someone
* not very familiar with p.
*/
class Facade {
public void doA() {/*...*/}
public void doB() {/*...*/}
/*...*/
}
Proxy:
interface Thing { void doit(); }
/* Sometimes runing on a different computer */
class RealThing implements Thing {
@Override public void doit() { /*...*/ }
}
class ProxyThing implements Thing {
@Override public void doit() { /* use RealThing to do most of the work */ }
}
/* Sometimes runing on a different computer */
class RealThing implements Thing {
@Override public void doit() { /*...*/ }
}
class ProxyThing implements Thing {
@Override public void doit() { /* use RealThing to do most of the work */ }
}
Command:
interface Closure { void go(); }
Chain of responsibility:
abstract class Chain {
public Chain next;
public setNext(Chain next) {
this.next = next;
return this;
}
public void doit(int mask, String arg) {
if (handle(mask)) reallyDoit(arg);
if (next != null) next.doit(mask, arg);
}
abstract protected boolean handle(int mask);
abstract protected void reallyDoit(String arg);
}
class ChainA extends Chain { /*...*/ }
class ChainB extends Chain { /*...*/ }
class ChainC extends Chain { /*...*/ }
class User {
void f() {
Chain c = new ChainA().setNext(new ChainB().setNext(new ChainC()));
/*...*/ c.doit(mask, arg); /*...*/
}
}
public Chain next;
public setNext(Chain next) {
this.next = next;
return this;
}
public void doit(int mask, String arg) {
if (handle(mask)) reallyDoit(arg);
if (next != null) next.doit(mask, arg);
}
abstract protected boolean handle(int mask);
abstract protected void reallyDoit(String arg);
}
class ChainA extends Chain { /*...*/ }
class ChainB extends Chain { /*...*/ }
class ChainC extends Chain { /*...*/ }
class User {
void f() {
Chain c = new ChainA().setNext(new ChainB().setNext(new ChainC()));
/*...*/ c.doit(mask, arg); /*...*/
}
}
Interpreter:
interface IntExpr { int eval(); }
interface BoolExpr { boolean eval(); }
class CompareIntExpr implements BoolExpr {
static enum CompareIntOp { LT, EQ, GT };
CompareIntOp op;
IntExpr left, right;
@Override public boolean eval() {
switch (op) {
case LT: return left.eval() < right.eval();
case EQ: return left.eval() == right.eval();
case GT: return left.eval() > right.eval();
}
assert false; return false;
}
}
/* and many other expressions... */
interface BoolExpr { boolean eval(); }
class CompareIntExpr implements BoolExpr {
static enum CompareIntOp { LT, EQ, GT };
CompareIntOp op;
IntExpr left, right;
@Override public boolean eval() {
switch (op) {
case LT: return left.eval() < right.eval();
case EQ: return left.eval() == right.eval();
case GT: return left.eval() > right.eval();
}
assert false; return false;
}
}
/* and many other expressions... */
Iterator:
interface Element {}
interface Iterator {
Element value();
void advance();
}
interface Collection {
Iterator first();
}
interface Iterator {
Element value();
void advance();
}
interface Collection {
Iterator first();
}
Memento:
class Thing {
public Object save() { /*...*/ }
public void restore(Object obj) {
Memento m = (Memento)obj;
/* use m to populate fields */
}
private static class Memento { /*...*/ }
}
public Object save() { /*...*/ }
public void restore(Object obj) {
Memento m = (Memento)obj;
/* use m to populate fields */
}
private static class Memento { /*...*/ }
}
Observer:
interface Observer { void update(); }
interface Subject {
void reg(Observer o);
void unreg(Observer o);
void notifyObservers();
}
interface Subject {
void reg(Observer o);
void unreg(Observer o);
void notifyObservers();
}
Strategy:
interface Strategy { void execute(/*...*/); }
class Context {
Strategy s;
public void execute(/*...*/) { /* delegates much to s.execute() */ }
}
class Context {
Strategy s;
public void execute(/*...*/) { /* delegates much to s.execute() */ }
}
Template method:
abstract class Class {
public void doit() { /* calls smallStepX */ }
abstract void smallStepA();
/*...*/
abstract void smallStepZ();
}
public void doit() { /* calls smallStepX */ }
abstract void smallStepA();
/*...*/
abstract void smallStepZ();
}
Visitor:
interface Ast { void accept(Visitor v); }
class AstA implements Ast { @Override void accept(Visitor v) { v.visit(this); } /*...*/ }
class AstB implements Ast { @Override void accept(Visitor v) { v.visit(this); } /*...*/ }
interface Visitor {
void visit(AstA a);
void visit(AstB b);
}
class AstA implements Ast { @Override void accept(Visitor v) { v.visit(this); } /*...*/ }
class AstB implements Ast { @Override void accept(Visitor v) { v.visit(this); } /*...*/ }
interface Visitor {
void visit(AstA a);
void visit(AstB b);
}
No comments:
Post a Comment
Note: (1) You need to have third-party cookies enabled in order to comment on Blogger. (2) Better to copy your comment before hitting publish/preview. Blogger sometimes eats comments on the first try, but the second works. Crazy Blogger.