Repository: iluwatar/java-design-patterns
Issue: Type Object pattern
Labels: epic: pattern

http://gameprogrammingpatterns.com/type-object.html

Issue comments:
Hello @iluwatar I would like to take this pattern. Thanks!
Ok @Imp92 
This issue is free for taking again
Hey, @iluwatar  I would like to take this pattern. Thanks.
@laubera ok
@laubera  are you still implementing this?
PR #848 

Pull request review comments:
does `start` and `end` both needs to current milliseconds?
same here. `start` and `end` are essentially the same.
It's needed so that we can enter into while loop

Patch that resolved the issue:
diff --git a/pom.xml b/pom.xml
index d5aba817058c..990a5a325cff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -165,6 +165,7 @@
 	<module>acyclic-visitor</module>
 	<module>collection-pipeline</module>
 	<module>spatial-partition</module>
+	<module>typeobjectpattern</module>
     </modules>
 
     <repositories>
diff --git a/typeobjectpattern/README.md b/typeobjectpattern/README.md
new file mode 100644
index 000000000000..97aa64e0b603
--- /dev/null
+++ b/typeobjectpattern/README.md
@@ -0,0 +1,29 @@
+---
+layout: pattern
+title: Type-object
+folder: typeobjectpattern
+permalink: /patterns/typeobjectpattern/
+categories: Game Programming Patterns/Behavioral Patterns
+tags:
+ - Java
+ - Difficulty-Beginner
+---
+
+## Intent
+As explained in the book Game Programming Patterns by Robert Nystrom, type object pattern helps in
+
+> Allowing flexible creation of new “classes” by creating a single class, each instance of which represents a different type of object
+
+## Applicability
+This pattern can be used when:
+* We don’t know what types we will need up front.
+* We want to be able to modify or add new types without having to recompile or change code.
+* Only difference between the different 'types' of objects is the data, not the behaviour.
+
+## Explanation
+Say, we are working on a game which has a hero and many monsters which are going to attack the hero. These monsters have certain attributes like attack, points etc. and come in different 'breeds' like zombie or ogres. The obvious answer is to have a base Monster class which has some fields and methods, which may be overriden by subclasses like the Zombie or Ogre class. But as we continue to build the game, there may be more and more breeds of monsters added and certain attributes may need to be changed in the existing monsters too. The OOP solution of inheriting from the base class would not be an efficient method in this case.
+Using the type-object pattern, instead of creating many classes inheriting from a base class, we have 1 class with a field which represents the 'type' of object. This makes the code cleaner and object instantiation also becomes as easy as parsing a json file with the object properties.
+ 
+## Credits
+* [Game Programming Patterns/Type Object](http://gameprogrammingpatterns.com/type-object.html) by Robert Nystrom
+* [http://www.cs.sjsu.edu/~pearce/modules/patterns/analysis/top.htm]
diff --git a/typeobjectpattern/pom.xml b/typeobjectpattern/pom.xml
new file mode 100644
index 000000000000..3377245f30ba
--- /dev/null
+++ b/typeobjectpattern/pom.xml
@@ -0,0 +1,31 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.iluwatar</groupId>
+    <artifactId>java-design-patterns</artifactId>
+    <version>1.21.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>typeobjectpattern</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>com.googlecode.json-simple</groupId>
+      <artifactId>json-simple</artifactId>
+      <version>1.1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/typeobjectpattern/src/main/java/com/iluwatar/typeobject/App.java b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/App.java
new file mode 100644
index 000000000000..f16777c686a3
--- /dev/null
+++ b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/App.java
@@ -0,0 +1,85 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import org.json.simple.parser.ParseException;
+
+/**<p>Type object pattern is the pattern we use when the OOP concept of creating a base class and
+ * inheriting from it just doesn't work for the case in hand. This happens when we either don't know 
+ * what types we will need upfront, or want to be able to modify or add new types conveniently w/o
+ * recompiling repeatedly. The pattern provides a solution by allowing flexible creation of required
+ * objects by creating one class, which has a field which represents the 'type' of the object.</p>
+ * <p>In this example, we have a mini candy-crush game in action. There are many different candies
+ * in the game, which may change over time, as we may want to upgrade the game. To make the object
+ * creation convenient, we have a class {@link Candy} which has a field name, parent, points and
+ * Type. We have a json file {@link candy} which contains the details about the candies, and this is
+ * parsed to get all the different candies in {@link JsonParser}. The {@link Cell} class is what the
+ * game matrix is made of, which has the candies that are to be crushed, and contains information on
+ * how crushing can be done, how the matrix is to be reconfigured and how points are to be gained. 
+ * The {@link CellPool} class is a pool which reuses the candy cells that have been crushed instead
+ * of making new ones repeatedly. The {@link CandyGame} class has the rules for the continuation of
+ * the game and the {@link App} class has the game itself.</p> 
+ */
+
+public class App {
+
+  /**
+   * Program entry point.
+   * @param args command line args
+   */
+  public static void main(String[] args) throws FileNotFoundException, IOException, ParseException {
+    int givenTime = 50; //50ms
+    int toWin = 500; //points
+    int pointsWon = 0;
+    int numOfRows = 3;
+    long start = System.currentTimeMillis();
+    long end = System.currentTimeMillis();
+    int round = 0;
+    while (pointsWon < toWin && end - start < givenTime) {      
+      round++;
+      CellPool pool = new CellPool(numOfRows * numOfRows + 5);
+      CandyGame cg = new CandyGame(numOfRows, pool);
+      if (round > 1) {
+        System.out.println("Refreshing..");
+      } else {
+        System.out.println("Starting game..");
+      }
+      cg.printGameStatus();
+      end = System.currentTimeMillis();
+      cg.round((int)(end - start), givenTime);
+      pointsWon += cg.totalPoints;
+      end = System.currentTimeMillis();
+    }
+    System.out.println("Game Over");
+    if (pointsWon >= toWin) {
+      System.out.println(pointsWon);
+      System.out.println("You win!!");
+    } else {
+      System.out.println(pointsWon);
+      System.out.println("Sorry, you lose!");
+    }
+  }
+}
diff --git a/typeobjectpattern/src/main/java/com/iluwatar/typeobject/Candy.java b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/Candy.java
new file mode 100644
index 000000000000..40b276e5bbc5
--- /dev/null
+++ b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/Candy.java
@@ -0,0 +1,60 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+/**
+ * The Candy class has a field type, which represents the 'type' of candy. The objects
+ * are created by parsing the candy.json file.
+ */
+
+public class Candy {
+  
+  enum Type { crushableCandy, rewardFruit };
+  
+  String name;
+  Candy parent;
+  String parentName;
+  private int points;
+  private Type type;
+  
+  Candy(String name, String parentName, Type type, int points) {
+    this.name = name;
+    this.parent = null;
+    this.type = type;
+    this.points = points;
+    this.parentName = parentName;
+  }
+  
+  int getPoints() {
+    return this.points;
+  }
+  
+  void setPoints(int a) {
+    this.points = a;
+  }
+  
+  Type getType() {
+    return this.type;
+  }
+}
diff --git a/typeobjectpattern/src/main/java/com/iluwatar/typeobject/CandyGame.java b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/CandyGame.java
new file mode 100644
index 000000000000..a2ba452ec03a
--- /dev/null
+++ b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/CandyGame.java
@@ -0,0 +1,171 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import java.util.ArrayList;
+import com.iluwatar.typeobject.Candy.Type;
+
+/**
+ * The CandyGame class contains the rules for the continuation of the game and has
+ * the game matrix (field 'cells') and totalPoints gained during the game.
+ */
+
+public class CandyGame {
+  Cell[][] cells;
+  CellPool pool;
+  int totalPoints;
+  
+  CandyGame(int num, CellPool pool) {
+    this.cells = new Cell[num][num];
+    this.pool = pool;
+    this.totalPoints = 0;
+    for (int i = 0; i < num; i++) {
+      for (int j = 0; j < num; j++) {
+        this.cells[i][j] = this.pool.getNewCell();
+        this.cells[i][j].xIndex = j;
+        this.cells[i][j].yIndex = i;
+      }
+    }
+  }
+  
+  static String numOfSpaces(int num) {
+    String result = "";
+    for (int i = 0; i < num; i++) {
+      result += " ";
+    }
+    return result;
+  }
+  
+  void printGameStatus() {
+    System.out.println("");
+    for (int i = 0; i < cells.length; i++) {
+      for (int j = 0; j < cells.length; j++) {
+        String candyName = cells[i][j].candy.name;
+        if (candyName.length() < 20) {
+          int totalSpaces = 20 - candyName.length();
+          System.out.print(numOfSpaces(totalSpaces / 2) + cells[i][j].candy.name
+              + numOfSpaces(totalSpaces - totalSpaces / 2) + "|");
+        } else {
+          System.out.print(candyName + "|");
+        }
+      }
+      System.out.println("");
+    }
+    System.out.println("");
+  }
+  
+  ArrayList<Cell> adjacentCells(int yIndex, int xIndex) {
+    ArrayList<Cell> adjacent = new ArrayList<Cell>();
+    if (yIndex == 0) {
+      adjacent.add(this.cells[1][xIndex]);
+    }
+    if (xIndex == 0) {
+      adjacent.add(this.cells[yIndex][1]);
+    }
+    if (yIndex == cells.length - 1) {
+      adjacent.add(this.cells[cells.length - 2][xIndex]);
+    }
+    if (xIndex == cells.length - 1) {
+      adjacent.add(this.cells[yIndex][cells.length - 2]);
+    }
+    if (yIndex > 0 && yIndex < cells.length - 1) {
+      adjacent.add(this.cells[yIndex - 1][xIndex]);
+      adjacent.add(this.cells[yIndex + 1][xIndex]);
+    }
+    if (xIndex > 0 && xIndex < cells.length - 1) {
+      adjacent.add(this.cells[yIndex][xIndex - 1]);
+      adjacent.add(this.cells[yIndex][xIndex + 1]);
+    }
+    return adjacent;
+  }
+   
+  boolean continueRound() {
+    for (int i = 0; i < this.cells.length; i++) {
+      if (this.cells[cells.length - 1][i].candy.getType().equals(Type.rewardFruit)) {
+        return true;
+      }
+    }
+    for (int i = 0; i < this.cells.length; i++) {
+      for (int j = 0; j < this.cells.length; j++) {
+        if (!this.cells[i][j].candy.getType().equals(Type.rewardFruit)) {
+          ArrayList<Cell> adj = adjacentCells(i,j);
+          for (int a = 0; a < adj.size(); a++) {
+            if (this.cells[i][j].candy.name.equals(adj.get(a).candy.name)) {
+              return true;
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+  
+  void handleChange(int points) {
+    System.out.println("+" + points + " points!");
+    this.totalPoints += points; 
+    printGameStatus();
+  }
+  
+  void round(int timeSoFar, int totalTime) {
+    long start = System.currentTimeMillis();
+    long end = System.currentTimeMillis();
+    while (end - start + timeSoFar < totalTime && continueRound()) {
+      for (int i = 0; i < this.cells.length; i++) {
+        int points = 0;
+        int j = this.cells.length - 1;
+        while (this.cells[j][i].candy.getType().equals(Type.rewardFruit)) {
+          points = this.cells[j][i].candy.getPoints();
+          this.cells[j][i].crush(pool, this.cells);
+          handleChange(points);
+        }
+      }
+      for (int i = 0; i < this.cells.length; i++) {
+        int j = cells.length - 1;
+        int points = 0;
+        while (j > 0) { 
+          points = this.cells[j][i].interact(this.cells[j - 1][i], this.pool, this.cells);
+          if (points != 0) {  
+            handleChange(points);
+          } else {
+            j = j - 1;
+          }
+        }
+      }
+      for (int i = 0; i < this.cells.length; i++) {
+        int j = 0;
+        int points = 0;
+        while (j < cells.length - 1) {       
+          points = this.cells[i][j].interact(this.cells[i][j + 1], this.pool, this.cells);
+          if (points != 0) {
+            handleChange(points);
+          } else {
+            j = j + 1;
+          }
+        }
+      }
+      end = System.currentTimeMillis();
+    }
+  }
+ 
+}
diff --git a/typeobjectpattern/src/main/java/com/iluwatar/typeobject/Cell.java b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/Cell.java
new file mode 100644
index 000000000000..7d0d696430fd
--- /dev/null
+++ b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/Cell.java
@@ -0,0 +1,90 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import com.iluwatar.typeobject.Candy.Type;
+
+/**
+ * The Cell object is what the game matrix is made of and contains the candy which is
+ * to be crushed or collected as reward.
+ */
+
+public class Cell {
+  Candy candy;
+  int xIndex;
+  int yIndex;
+  
+  Cell(Candy candy, int xIndex, int yIndex) {
+    this.candy = candy;
+    this.xIndex = xIndex;
+    this.yIndex = yIndex;
+  }
+  
+  Cell() {
+    this.candy = null;
+    this.xIndex = 0;
+    this.yIndex = 0;
+  }
+  
+  void crush(CellPool pool, Cell[][] cellMatrix) {
+    //take out from this position and put back in pool
+    pool.addNewCell(this);
+    this.fillThisSpace(pool, cellMatrix);
+  }
+  
+  void fillThisSpace(CellPool pool, Cell[][] cellMatrix) {
+    for (int y = this.yIndex; y > 0; y--) {
+      cellMatrix[y][this.xIndex] = cellMatrix[y - 1][this.xIndex];
+      cellMatrix[y][this.xIndex].yIndex = y;
+    }
+    Cell newC = pool.getNewCell();
+    cellMatrix[0][this.xIndex] = newC;
+    cellMatrix[0][this.xIndex].xIndex = this.xIndex;
+    cellMatrix[0][this.xIndex].yIndex = 0;
+  }
+  
+  void handleCrush(Cell c, CellPool pool, Cell[][] cellMatrix) {
+    if (this.yIndex >= c.yIndex) {      
+      this.crush(pool, cellMatrix);       
+      c.crush(pool, cellMatrix);
+    } else {
+      c.crush(pool, cellMatrix);
+      this.crush(pool, cellMatrix);
+    }
+  }
+  
+  int interact(Cell c, CellPool pool, Cell[][] cellMatrix) {
+    if (this.candy.getType().equals(Type.rewardFruit) || c.candy.getType().equals(Type.rewardFruit)) {
+      return 0;
+    } else {
+      if (this.candy.name.equals(c.candy.name)) {
+        int pointsWon = this.candy.getPoints() + c.candy.getPoints();
+        handleCrush(c,pool,cellMatrix);
+        return pointsWon;
+      } else {
+        return 0;
+      }
+    }
+  }
+}
diff --git a/typeobjectpattern/src/main/java/com/iluwatar/typeobject/CellPool.java b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/CellPool.java
new file mode 100644
index 000000000000..88263ceab57d
--- /dev/null
+++ b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/CellPool.java
@@ -0,0 +1,96 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Random;
+import org.json.simple.parser.ParseException;
+import com.iluwatar.typeobject.Candy.Type;
+
+/**
+ * The CellPool class allows the reuse of crushed cells instead of creation of new
+ * cells each time. The reused cell is given a new candy to hold using the randomCode
+ * field which holds all the candies available.
+ */
+
+public class CellPool {
+  ArrayList<Cell> pool;
+  int pointer;
+  Candy[] randomCode;
+  
+  CellPool(int num) {
+    this.pool = new ArrayList<Cell>(num);    
+    try {
+      this.randomCode = assignRandomCandytypes();
+    } catch (Exception e) {
+      e.printStackTrace();
+      //manually initialising this.randomCode
+      this.randomCode = new Candy[5];
+      randomCode[0] = new Candy("cherry", "fruit", Type.rewardFruit, 20);
+      randomCode[1] = new Candy("mango", "fruit", Type.rewardFruit, 20);
+      randomCode[2] = new Candy("purple popsicle", "candy", Type.crushableCandy, 10);
+      randomCode[3] = new Candy("green jellybean", "candy", Type.crushableCandy, 10);
+      randomCode[4] = new Candy("orange gum", "candy", Type.crushableCandy, 10);
+    }
+    for (int i = 0; i < num; i++) {
+      Cell c = new Cell();
+      Random rand = new Random();
+      c.candy = randomCode[rand.nextInt(randomCode.length)];
+      this.pool.add(c);
+    }
+    this.pointer = num - 1;
+  }
+  
+  Cell getNewCell() {
+    Cell newCell = this.pool.remove(pointer);
+    pointer--;
+    return newCell;
+  }
+  
+  void addNewCell(Cell c) {
+    Random rand = new Random();
+    c.candy = randomCode[rand.nextInt(randomCode.length)]; //changing candytype to new
+    this.pool.add(c);
+    pointer++;
+  }
+  
+  Candy[] assignRandomCandytypes() throws FileNotFoundException, IOException, ParseException {
+    JsonParser jp = new JsonParser();
+    jp.parse();
+    Candy[] randomCode = new Candy[jp.candies.size() - 2]; //exclude generic types 'fruit' and 'candy'
+    int i = 0;
+    for (Enumeration<String> e = jp.candies.keys(); e.hasMoreElements();) {
+      String s = e.nextElement();
+      if (!s.equals("fruit") && !s.equals("candy")) {
+        //not generic
+        randomCode[i] = jp.candies.get(s);
+        i++;
+      }
+    }
+    return randomCode;
+  }
+}
diff --git a/typeobjectpattern/src/main/java/com/iluwatar/typeobject/JsonParser.java b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/JsonParser.java
new file mode 100644
index 000000000000..6c6bfa616a34
--- /dev/null
+++ b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/JsonParser.java
@@ -0,0 +1,87 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import com.iluwatar.typeobject.Candy.Type;
+
+/**
+ * The JsonParser class helps parse the json file candy.json to get all the
+ * different candies.
+ */
+
+public class JsonParser {
+  Hashtable<String, Candy> candies;
+  
+  JsonParser() {
+    this.candies = new Hashtable<String, Candy>();
+  }
+
+  void parse() throws FileNotFoundException, IOException, ParseException {
+    JSONParser parser = new JSONParser();
+    JSONObject jo = (JSONObject) parser.parse(new FileReader(new File("").getAbsolutePath()
+        + "\\src\\main\\java\\com\\iluwatar\\typeobject\\candy.json"));
+    JSONArray a = (JSONArray) jo.get("candies");
+    for (Object o : a) {
+      JSONObject candy = (JSONObject) o;
+      String name = (String) candy.get("name");
+      String parentName = (String) candy.get("parent");
+      String t = (String) candy.get("type");
+      Type type = null;
+      if (t.equals("rewardFruit")) {
+        type = Type.rewardFruit;
+      } else {
+        type = Type.crushableCandy;
+      }
+      int points = Integer.parseInt((String) candy.get("points"));
+      Candy c = new Candy(name, parentName, type, points);
+      this.candies.put(name, c);
+    }
+    setParentAndPoints();
+  }
+  
+  void setParentAndPoints() {
+    for (Enumeration<String> e = this.candies.keys(); e.hasMoreElements();) {
+      Candy c = this.candies.get(e.nextElement());
+      if (c.parentName == null) {
+        c.parent = null;
+      } else {
+        c.parent = this.candies.get(c.parentName);
+      }
+      if (c.getPoints() == 0 && c.parent != null) {
+        c.setPoints(c.parent.getPoints());
+      }
+    }
+  }
+
+}
diff --git a/typeobjectpattern/src/main/java/com/iluwatar/typeobject/candy.json b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/candy.json
new file mode 100644
index 000000000000..74430c318d72
--- /dev/null
+++ b/typeobjectpattern/src/main/java/com/iluwatar/typeobject/candy.json
@@ -0,0 +1,45 @@
+{"candies" : [
+  {
+    "name" : "fruit",
+    "parent" : "null",
+    "type" : "rewardFruit",
+    "points" : "20"
+  },
+  {
+    "name" : "candy",
+    "parent" : "null",
+    "type" : "crushableCandy",
+    "points" : "10"
+  },
+  {
+    "name" : "cherry",
+    "parent" : "fruit",
+    "type" : "rewardFruit",
+    "points" : "0"
+  },
+  {
+    "name" : "mango",
+    "parent" : "fruit",
+    "type" : "rewardFruit",
+    "points" : "0"
+  },
+  {
+    "name" : "purple popsicle",
+    "parent" : "candy",
+    "type" : "crushableCandy",
+    "points" : "0"
+  },
+  {
+    "name" : "green jellybean",
+    "parent" : "candy",
+    "type" : "crushableCandy",
+    "points" : "0"
+  },
+  {
+    "name" : "orange gum",
+    "parent" : "candy",
+    "type" : "crushableCandy",
+    "points" : "0"
+  }
+  ]
+}


Test patch:
diff --git a/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CandyGameTest.java b/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CandyGameTest.java
new file mode 100644
index 000000000000..d1b2fd359385
--- /dev/null
+++ b/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CandyGameTest.java
@@ -0,0 +1,69 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
+import com.iluwatar.typeobject.Candy.Type;
+
+/**
+ * The CandyGameTest class tests the methods in the {@link CandyGame} class.
+ */
+
+class CandyGameTest {
+
+  @Test
+  void adjacentCellsTest() {
+    CandyGame cg = new CandyGame(3,new CellPool(9));
+    ArrayList<Cell> arr1 = cg.adjacentCells(0, 0);
+    ArrayList<Cell> arr2 = cg.adjacentCells(1, 2);
+    ArrayList<Cell> arr3 = cg.adjacentCells(1, 1);
+    assertTrue(arr1.size() == 2 && arr2.size() == 3 && arr3.size() == 4);
+  }
+
+  @Test
+  void continueRoundTest() {
+    Cell[][] matrix = new Cell[2][2];
+    Candy c1 = new Candy("green jelly", "jelly", Type.crushableCandy, 5);
+    Candy c2 = new Candy("purple jelly", "jelly", Type.crushableCandy, 5);
+    Candy c3 = new Candy("green apple", "apple", Type.rewardFruit, 10);
+    matrix[0][0] = new Cell(c1,0,0);;
+    matrix[0][1] = new Cell(c2,1,0);
+    matrix[1][0] = new Cell(c3,0,1);
+    matrix[1][1] = new Cell(c2,1,1);
+    CellPool p = new CellPool(4);
+    CandyGame cg = new CandyGame(2,p);
+    cg.cells = matrix;
+    boolean fruitInLastRow = cg.continueRound();
+    matrix[1][0].crush(p, matrix);
+    matrix[0][0] = new Cell(c3,0,0);
+    boolean matchingCandy = cg.continueRound(); 
+    matrix[0][1].crush(p,matrix);
+    matrix[0][1] = new Cell(c3,1,0);
+    boolean noneLeft = cg.continueRound();
+    assertTrue(fruitInLastRow && matchingCandy && !noneLeft);
+  }
+
+}
diff --git a/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CellPoolTest.java b/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CellPoolTest.java
new file mode 100644
index 000000000000..437e39d1abd3
--- /dev/null
+++ b/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CellPoolTest.java
@@ -0,0 +1,52 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
+import java.util.Hashtable;
+
+/**
+ * The CellPoolTest class tests the methods in the {@link CellPool} class.
+ */
+
+class CellPoolTest {
+
+  @Test
+  void assignRandomCandyTypesTest() {
+    CellPool cp = new CellPool(10);
+    Hashtable<String, Boolean> ht = new Hashtable<String, Boolean>();
+    int parentTypes = 0;
+    for (int i = 0; i < cp.randomCode.length; i++) {
+      if (ht.get(cp.randomCode[i].name) == null) {
+        ht.put(cp.randomCode[i].name, true);
+      }
+      if (cp.randomCode[i].name.equals("fruit") || cp.randomCode[i].name.equals("candy")) {
+        parentTypes++;
+      }
+    }
+    assertTrue(ht.size() == 5 && parentTypes == 0);
+  }
+
+}
diff --git a/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CellTest.java b/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CellTest.java
new file mode 100644
index 000000000000..b4118cb48651
--- /dev/null
+++ b/typeobjectpattern/src/test/java/com/iluwatar/typeobject/CellTest.java
@@ -0,0 +1,61 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014-2016 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.typeobject;
+
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
+import com.iluwatar.typeobject.Candy.Type;
+
+/**
+ * The CellTest class tests the methods in the {@link Cell} class.
+ */
+
+class CellTest {
+
+  @Test
+  void interactTest() {
+    Candy c1 = new Candy("green jelly", "jelly", Type.crushableCandy, 5);
+    Candy c2 = new Candy("green apple", "apple", Type.rewardFruit, 10);
+    Cell[][] matrix = new Cell[4][4];
+    matrix[0][0] = new Cell(c1,0,0);
+    matrix[0][1] = new Cell(c1,1,0);
+    matrix[0][2] = new Cell(c2,2,0);
+    matrix[0][3] = new Cell(c1,3,0);
+    CellPool cp = new CellPool(5);
+    int points1 = matrix[0][0].interact(matrix[0][1], cp, matrix);
+    int points2 = matrix[0][2].interact(matrix[0][3], cp, matrix);
+    assertTrue(points1 > 0 && points2 == 0);
+  }
+
+  @Test
+  void crushTest() {
+    Candy c1 = new Candy("green jelly", "jelly", Type.crushableCandy, 5);
+    Candy c2 = new Candy("purple candy", "candy", Type.crushableCandy, 5);
+    Cell[][] matrix = new Cell[4][4];
+    matrix[0][0] = new Cell(c1,0,0);
+    matrix[1][0] = new Cell(c2,0,1);
+    matrix[1][0].crush(new CellPool(5), matrix);
+    assertTrue(matrix[1][0].candy.name.equals("green jelly"));
+  }
+}