Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract factory implementation #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/main/java/GameLauncher.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import domain.LabyrinthGame;
import factories.BombedLabyrinthFactory;
import factories.LabyrinthFactory;

public class GameLauncher {
public static void main(String[] args) {
LabyrinthGame game = new LabyrinthGame();
game.createLabyrinth();
LabyrinthFactory factory = new BombedLabyrinthFactory();

game.createLabyrinth(factory);
}
}
1 change: 1 addition & 0 deletions src/main/java/domain/Door.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package domain;

import domain.exceptions.CannotGoThroughObjectException;
import domain.interfaces.MapSite;

public class Door implements MapSite {
private Room oneRoom;
Expand Down
33 changes: 21 additions & 12 deletions src/main/java/domain/LabyrinthGame.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
package domain;

import factories.LabyrinthFactory;

public class LabyrinthGame {
/**
* TODO: this hardcoded creation will be replaced with creational design patterns as in the GoF book
* Recall that the member function createLabyrinth builds a small
* Labyrinth consisting of two rooms with a door between them. But createLabyrinth
* hard-coded the class names, making it difficult to create Labyrinths with
* different components.
* Here’s a version of createLabyrinth that remedies that shortcoming by
* taking a MazeFactory as a parameter:
*
* @param factory A concrete theme for the game
*/
public Labyrinth createLabyrinth() {
Room firstRoom = new Room(1);
Room secondRoom = new Room(2);
public static Labyrinth createLabyrinth(LabyrinthFactory factory) {
Room firstRoom = factory.createRoom(1);
Room secondRoom = factory.createRoom(2);

Door aDoor = new Door(firstRoom, secondRoom);
Door aDoor = factory.createDoor(firstRoom, secondRoom);

firstRoom.setSide(Direction.NORTH, new Wall());
firstRoom.setSide(Direction.NORTH, factory.createWall());
firstRoom.setSide(Direction.SOUTH, aDoor);
firstRoom.setSide(Direction.EAST, new Wall());
firstRoom.setSide(Direction.WEST, new Wall());
firstRoom.setSide(Direction.EAST, factory.createWall());
firstRoom.setSide(Direction.WEST, factory.createWall());

secondRoom.setSide(Direction.NORTH, aDoor);
secondRoom.setSide(Direction.SOUTH, new Wall());
secondRoom.setSide(Direction.EAST, new Wall());
secondRoom.setSide(Direction.WEST, new Wall());
secondRoom.setSide(Direction.SOUTH, factory.createWall());
secondRoom.setSide(Direction.EAST, factory.createWall());
secondRoom.setSide(Direction.WEST, factory.createWall());

Labyrinth labyrinth = new Labyrinth();
Labyrinth labyrinth = factory.createLabyrinth();
labyrinth.addRoom(firstRoom);
labyrinth.addRoom(secondRoom);

Expand Down
1 change: 1 addition & 0 deletions src/main/java/domain/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import domain.exceptions.CannotGoThroughObjectException;
import domain.exceptions.NotADoorException;
import domain.interfaces.MapSite;

import java.util.HashMap;
import java.util.Map;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/domain/Wall.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package domain;

import domain.exceptions.CannotGoThroughObjectException;
import domain.interfaces.MapSite;

public class Wall implements MapSite {
@Override
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/domain/bombedLabyrinth/BombedWall.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package domain.bombedLabyrinth;

import domain.Wall;

public class BombedWall extends Wall {
public BombedWall() {
System.out.println("If a bomb goes off, it will damage this wall");
}
}
11 changes: 11 additions & 0 deletions src/main/java/domain/bombedLabyrinth/RoomWithABomb.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package domain.bombedLabyrinth;

import domain.Room;

public class RoomWithABomb extends Room {
public RoomWithABomb(int number) {
super(number);
System.out.println("This room keeps track of whether the\n" +
"room has a bomb in it and whether the bomb has gone off");
}
}
11 changes: 11 additions & 0 deletions src/main/java/domain/enchantedLabyrinth/DoorNeedingSpell.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package domain.enchantedLabyrinth;

import domain.Door;
import domain.Room;

public class DoorNeedingSpell extends Door {
public DoorNeedingSpell(Room aRoom, Room anotherRoom) {
super(aRoom, anotherRoom);
System.out.println("Will not open without a spell");
}
}
10 changes: 10 additions & 0 deletions src/main/java/domain/enchantedLabyrinth/EnchantedRoom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package domain.enchantedLabyrinth;

import domain.Room;

public class EnchantedRoom extends Room {
public EnchantedRoom(int number) {
super(number);
System.out.println("Strange things will happen here.");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package domain;
package domain.interfaces;

import domain.Room;
import domain.exceptions.CannotGoThroughObjectException;

public interface MapSite {
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/factories/BombedLabyrinthFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package factories;

import domain.Room;
import domain.Wall;
import domain.bombedLabyrinth.BombedWall;
import domain.bombedLabyrinth.RoomWithABomb;

public class BombedLabyrinthFactory extends LabyrinthFactory {
@Override
public Room createRoom(int number) {
return new RoomWithABomb(number);
}

@Override
public Wall createWall() {
return new BombedWall();
}
}
19 changes: 19 additions & 0 deletions src/main/java/factories/EnchantedLabyrinthFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package factories;

import domain.enchantedLabyrinth.DoorNeedingSpell;
import domain.enchantedLabyrinth.EnchantedRoom;
import domain.Door;
import domain.Room;

public class EnchantedLabyrinthFactory extends LabyrinthFactory {

@Override
public Room createRoom(int number) {
return new EnchantedRoom(number);
}

@Override
public Door createDoor(Room aRoom, Room anotherRoom) {
return new DoorNeedingSpell(aRoom, anotherRoom);
}
}
33 changes: 33 additions & 0 deletions src/main/java/factories/LabyrinthFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package factories;

import domain.Door;
import domain.Labyrinth;
import domain.Room;
import domain.Wall;

/**
* Note in the book that LabyrinthFactory is not an abstract class; thus it
* acts as both the AbstractFactory and the ConcreteFactory. That is
* another common implementation for simple applications of the
* Abstract Factory pattern. Because the LabyrinthFactory is a concrete class
* consisting entirely of factory methods, it’s easy to make a new
* LabyrinthFactory by making a subclass and overriding the operations that
* need to change.
*/
public abstract class LabyrinthFactory {
public Labyrinth createLabyrinth() {
return new Labyrinth();
}

public Room createRoom(int number) {
return new Room(number);
}

public Wall createWall() {
return new Wall();
}

public Door createDoor(Room aRoom, Room anotherRoom) {
return new Door(aRoom, anotherRoom);
}
}
72 changes: 38 additions & 34 deletions src/test/java/domain/integration/LabyrinthGameShould.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
package domain.integration;

import domain.*;
import domain.exceptions.CannotGoThroughObjectException;
import domain.exceptions.RoomNotFoundException;
import org.assertj.core.api.Assertions;
import org.junit.Test;

public class LabyrinthGameShould {
@Test
public void
can_go_from_one_room_to_another() throws RoomNotFoundException, CannotGoThroughObjectException {
LabyrinthGame game = new LabyrinthGame();
Labyrinth labyrinth = game.createLabyrinth();

Room firstRoom = labyrinth.getRoom(1);
Room secondRoom = firstRoom.go(Direction.SOUTH);

Assertions.assertThat(secondRoom).isEqualTo(labyrinth.getRoom(2));
}

@Test
public void
cannot_go_from_one_room_to_another_when_door_is_closed() throws RoomNotFoundException {
LabyrinthGame game = new LabyrinthGame();
Labyrinth labyrinth = game.createLabyrinth();

Room firstRoom = labyrinth.getRoom(1);

Door theDoor = (Door) firstRoom.getSide(Direction.SOUTH);
theDoor.close();

Assertions.assertThatThrownBy(() -> firstRoom.go(Direction.SOUTH)).isInstanceOf(CannotGoThroughObjectException.class);
}
package domain.integration;

import domain.*;
import domain.exceptions.CannotGoThroughObjectException;
import domain.exceptions.RoomNotFoundException;
import factories.EnchantedLabyrinthFactory;
import factories.LabyrinthFactory;
import org.assertj.core.api.Assertions;
import org.junit.Test;

public class LabyrinthGameShould {
@Test
public void
can_go_from_one_room_to_another() throws RoomNotFoundException, CannotGoThroughObjectException {
LabyrinthGame game = new LabyrinthGame();
LabyrinthFactory factory = new EnchantedLabyrinthFactory();
Labyrinth labyrinth = game.createLabyrinth(factory);

Room firstRoom = labyrinth.getRoom(1);
Room secondRoom = firstRoom.go(Direction.SOUTH);

Assertions.assertThat(secondRoom).isEqualTo(labyrinth.getRoom(2));
}

@Test
public void
cannot_go_from_one_room_to_another_when_door_is_closed() throws RoomNotFoundException {
LabyrinthGame game = new LabyrinthGame();
LabyrinthFactory factory = new EnchantedLabyrinthFactory();
Labyrinth labyrinth = game.createLabyrinth(factory);

Room firstRoom = labyrinth.getRoom(1);

Door theDoor = (Door) firstRoom.getSide(Direction.SOUTH);
theDoor.close();

Assertions.assertThatThrownBy(() -> firstRoom.go(Direction.SOUTH)).isInstanceOf(CannotGoThroughObjectException.class);
}
}