kenu / solid star
dboyliao 2015-11-25
Initial commit. Add example code for open/close principle.
@9a828ee80bb00ecb05f13f4fda67c0d29b5948a1
 
python_code/__init__.py (added)
+++ python_code/__init__.py
@@ -0,0 +1,0 @@
 
python_code/__init__.pyc (Binary) (added)
+++ python_code/__init__.pyc
Binary file is not shown
 
python_code/bad/__init__.py (added)
+++ python_code/bad/__init__.py
@@ -0,0 +1,0 @@
 
python_code/bad/__init__.pyc (Binary) (added)
+++ python_code/bad/__init__.pyc
Binary file is not shown
 
python_code/bad/open_close.py (added)
+++ python_code/bad/open_close.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Think about what will happen if you want to extend the class to calculate
+# the area of different shape? What would you do with the code in the property
+# `total_area` of class `AreaCalculator`?
+
+class Rectangle(object):
+
+    def __init__(self, width, height):
+        self.width = width
+        self.height = height
+
+class AreaCalculator(object):
+
+    def __init__(self, shapes):
+
+        assert isinstance(shapes, list), "`shapes` should be of type `list`."
+        self.shapes = shapes
+
+    @property
+    def total_area(self):
+        total = 0
+        for shape in self.shapes:
+            total += shape.width * shape.height
+
+        return total
+
+def main():
+    shapes = [Rectangle(2, 3), Rectangle(1, 6)]
+    calculator = AreaCalculator(shapes)
+    print "The total area is: ", calculator.total_area
+
+if __name__ == '__main__':
+
+    main()
 
python_code/good/__init__.py (added)
+++ python_code/good/__init__.py
@@ -0,0 +1,0 @@
 
python_code/good/__init__.pyc (Binary) (added)
+++ python_code/good/__init__.pyc
Binary file is not shown
 
python_code/good/open_close.py (added)
+++ python_code/good/open_close.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# This is a reimplementation of `python_code.bad.open_close` module which
+# abides by the open/close principle. You can see that it will be easy to
+# extend the functionality of `AreaCalculator` in this module whereas it
+# is not in `python_code.bad.open_close` module.
+
+from abc import ABCMeta, abstractproperty
+
+class Shape(object):
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
+    def area(self):
+        pass
+
+class Rectangle(Shape):
+
+    def __init__(self, width, height):
+        self.width = width
+        self.height = height
+
+    @property
+    def area(self):
+        return self.width * self.height
+
+class AreaCalculator(object):
+
+    def __init__(self, shapes):
+        self.shapes = shapes
+
+    @property
+    def total_area(self):
+        total = 0
+        for shape in self.shapes:
+            total += shape.area
+        return total
+
+# Note that if we want to extend the functionality of AreaCalculator to support calculating
+# area of different shape, we only need to define new subtype of `Shape` and leave other code
+# alone without modify them. That is the key of open/close principle.
+
+def main():
+    shapes = [Rectangle(1, 6), Rectangle(2, 3)]
+    calculator = AreaCalculator(shapes)
+
+    print "The total area is: ", calculator.total_area
+
+if __name__ == '__main__':
+    main()
Add a comment
List