Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Last active August 29, 2015 14:00
Show Gist options
  • Save rikkimax/e536b5850e6ef17c2b68 to your computer and use it in GitHub Desktop.
Save rikkimax/e536b5850e6ef17c2b68 to your computer and use it in GitHub Desktop.
Design patterns examples
abstract class WidgetFactory {
ScrollBar createScrollBar();
Window createWindow();
}
class PMWidgetFactory : WidgetFactory {
override ScrollBar createScrollBar() {
return new PMScrollBar();
}
override Window createWindow() {
return new PMWindow();
}
}
class MotifWidgetFactory : WidgetFactory {
override ScrollBar createScrollBar() {
return new MotifScrollBar();
}
override Window createWindow() {
return MotifWindow();
}
}
abstract class Window {
}
class PMWindow : Window {
}
class MotifWindow : Window {
}
abstract class ScrollBar {
}
class PMScrollBar : ScrollBar {
}
class MotifScrollBar : ScrollBar {
}
class ClientCode {
Config config;
WidgetFactory factory;
this(Config config) {
this.config = config;
if (config.isMotif) {
this.factory = new MotifWidgetFactory();
} else {
this.factory = new PMWidgetFactory();
}
}
}
class WidgetFactory:
def createScrollBar(self):
pass
def createWindow(self):
pass
class PMWidgetFactory(WidgetFactory):
def createScrollBar(self):
return PMScrollBar()
def createWindow(self):
return PMWindow()
class MotifWidgetFactory(WidgetFactory):
def createScrollBar(self):
return MotifScrollBar()
def createWindow(self):
return MotifWindow()
class Window:
pass
class PMWindow(Window):
pass
class MotifWindow(Window):
pass
class ClientCode:
def __init__(self, config):
self.config = config
if self.config.isMotif:
self.factory = MotifWidgetFactory()
else:
self.factory = PMWidgetFactory()
class RTFReader {
TextConverter builder;
this(TextConverter builder) {
this.builder = builder;
}
void parseRTF() {
// while(t = /*get the next token*/) {
// switch(t.type) {
// case CHAR:
// builder.convertCharacter(t.char);
// break;
// case FONT:
// builder.convertFontChange(t.font);
// break;
// case PARA:
// builder.convertParagraph()
// break;
// }
// }
}
}
abstract class TextConverter {
void convertCharacter(char c);
void convertFontChange(Font f);
void convertParagraph();
}
class ASCIIConverter : TextConverter {
override void convertCharacter(char c) {
// ...
}
// not used
override void convertFontChange(Font f) {}
// not used
overide void convertParagraph() {}
ASCIIText getASCIIText() {
// ...
}
}
class TexConverter : TextConverter {
override void convertCharacter(char c) {
}
override void convertFontChange(Font f) {
// ...
}
overide void convertParagraph() {
// ...
}
TexText getTexText() {
// ...
}
}
class TextWidgetConverter : TextConverter {
override void convertCharacter(char c) {
}
override void convertFontChange(Font f) {
// ...
}
overide void convertParagraph() {
// ...
}
TextWidget getTextWidget() {
// ...
}
}
class RTFReader:
def __init__(self, builder):
self.builder = builder
def parseRTF(self):
while t = """get the next token""":
if t.type == CHAR:
self.builder.convertCharacter(t.char)
elif t.type == FONT:
self.builder.convertFontChange(t.font)
elif t.type == PARA:
self.builder.convertParagraph()
class TextConverter:
def convertCharacter(self, c):
pass
def convertFontChange(self, f):
pass
def convertParagraph(self):
pass
class ASCIIConverter(TextConverter):
def convertCharacter(self, c):
pass
def getASCIIText(self):
pass
class TexConverter(TextConverter):
def convertCharacter(self, c):
pass
def convertFontChange(self, f):
pass
def convertParagraph(self):
pass
def getTexText(self):
pass
class TextWidgetConverter(TextConverter):
def convertCharacter(self, c):
pass
def convertFontChange(self, f):
pass
def convertParagraph(self):
pass
def getTextWidget(self):
pass
abstract class Document {
void open();
void close();
void save();
void revert();
}
abstract class Application {
Document[] docs;
Document createDocument();
void newDocument() {
Document doc = createDocument();
docs ~= doc;
doc.open();
}
void openDocument();
}
class MyDocument : Document {
overide void open() {}
overide void close() {}
overide void save() {}
overide void revert() {}
}
class MyApplication : Application {
overide Document createDocument() {
return new MyDocument();
}
overide void openDocument() {}
}
void clientCode() {
Application app = new MyApplication();
app.newDocument();
}
class Document:
def open(self):
pass
def close(self):
pass
def save(self):
pass
def revert(self):
pass
class Application:
def __init__(self):
self.docs = []
def createDocument(self):
pass
def newDocument(self):
doc = createDocument(self)
self.docs.append(doc)
doc.open()
def openDocument(self):
pass
class MyDocument(Document):
pass
class MyApplication(Application):
def createDocument(self):
return MyDocument()
def clientCode():
app = MyApplication()
app.newDocument()
import std.stdio : writeln;
abstract class Figure {
Manipulator createManipulator();
}
class LineFigure : Figure {
override Manipulator createManipulator() {
return new LineManipulator();
}
}
class TextFigure : Figure {
override Manipulator createManipulator() {
return new TextManipulator();
}
}
abstract class Manipulator {
void downClick();
void drag();
void upClick();
}
class LineManipulator : Manipulator {
override void downClick() {
writeln("down click");
}
override void drag() {
writeln("dragging");
}
override void upClick() {
writeln("stopped clicking");
}
}
class TextManipulator : Manipulator {
override void downClick() {
writeln("me go clicky downy");
}
override void drag() {
writeln("draggy goes the mouse");
}
override void upClick() {
writeln("no more clicky clicky");
}
}
void clientCode() {
Figure figure = new LineFigure();
Manipulator manipulator = figure.createManipulator();
manipulator.downClick();
}
class Figure:
def createManipulator(self):
pass
class LineFigure(Figure):
def createManipulator(self):
return LineManipulator()
class TextFigure(Figure):
def createManipulator(self):
return TextManipulator()
class Manipulator:
def downClick(self):
pass
def drag(self):
pass
def upClick(self):
pass
class LineManipulator(Manipulator):
def downClick(self):
print("down click")
def drag(self):
print("dragging")
def upClick(self):
print("stopped clicking")
class TextManipulator(Manipulator):
def downClick(self):
print("me go clicky downy")
def drag(self):
print("draggy goes the mouse")
def upClick(self):
print("no more clicky clicky")
def clientCode():
figure = LineFigure()
manipulator = figure.createManipulator()
manipulator.downClick()

Notes

Rules:

  • Program to an interface not an implementation
  • Favour object composition over class inheritance

Common redesign reasons:

  • Creating an object class specifically, favour instead indirect methods. Commiting yourself to a particular implementation only hinders e.g. porting and changing things.
  • Dependence on specific operations, when requesting from external entities don't directly do it. You're locking yourself into only one way of getting that information.
  • Dependence on hardware and software platform, limit the dependence on the system itself directly. Instead use platform independent abstractions to limit porting issues.
  • Dependence on object representations or implementations, how a peice of data is stored or used should not be directly accessible. A common interface should be instead perferred so any changes in the implementation itself can hide how its stored (to prevent user code to be dependent on how the code implementation works).
  • Algorithmic dependencies, if an algorithym is likely to be changed it should be isolate so that it can be dealt with as little as user code to be needed to be modified when it changes as possible.
  • Tight coupling, when classes care about other classes existing too much. It forces having to have all or nothing code bases where the porting to other systems are hard to do.
  • Extending functionality by subclassing, use composition instead of inheriting clsses. Inheriting classes means understanding the parent class and how it works which may not be easy. If needed sub classing to make it easy to work with is possible and then use with composition to extend the program.
  • Inability to alter classes conveniently, having the need to alter a class where the source may not be available or inedible means the design to get it were unacceptable. In such a factory should be implemented and then extended upon to provide the functionality required.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment