Reformat rest of the design patterns - Issue #224
This commit is contained in:
parent
449340bd2b
commit
306b1f3d31
@ -6,38 +6,37 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* Double Checked Locking is a concurrency design pattern used to reduce the overhead
|
||||
* of acquiring a lock by first testing the locking criterion (the "lock hint") without
|
||||
* actually acquiring the lock. Only if the locking criterion check indicates that
|
||||
* locking is required does the actual locking logic proceed.
|
||||
* Double Checked Locking is a concurrency design pattern used to reduce the overhead of acquiring a
|
||||
* lock by first testing the locking criterion (the "lock hint") without actually acquiring the
|
||||
* lock. Only if the locking criterion check indicates that locking is required does the actual
|
||||
* locking logic proceed.
|
||||
* <p>
|
||||
* In {@link Inventory} we store the items with a given size. However, we do not store
|
||||
* more items than the inventory size. To address concurrent access problems we
|
||||
* use double checked locking to add item to inventory. In this method, the
|
||||
* thread which gets the lock first adds the item.
|
||||
* In {@link Inventory} we store the items with a given size. However, we do not store more items
|
||||
* than the inventory size. To address concurrent access problems we use double checked locking to
|
||||
* add item to inventory. In this method, the thread which gets the lock first adds the item.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
final Inventory inventory = new Inventory(1000);
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
executorService.execute(() -> {
|
||||
while (inventory.addItem(new Item()))
|
||||
;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
final Inventory inventory = new Inventory(1000);
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
executorService.execute(() -> {
|
||||
while (inventory.addItem(new Item()));
|
||||
});
|
||||
}
|
||||
|
||||
executorService.shutdown();
|
||||
try {
|
||||
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Error waiting for ExecutorService shutdown");
|
||||
}
|
||||
}
|
||||
executorService.shutdown();
|
||||
try {
|
||||
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Error waiting for ExecutorService shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,32 +12,30 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
public class Inventory {
|
||||
|
||||
private final int inventorySize;
|
||||
private final List<Item> items;
|
||||
private final Lock lock;
|
||||
private final int inventorySize;
|
||||
private final List<Item> items;
|
||||
private final Lock lock;
|
||||
|
||||
public Inventory(int inventorySize) {
|
||||
this.inventorySize = inventorySize;
|
||||
this.items = new ArrayList<>(inventorySize);
|
||||
this.lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
public boolean addItem(Item item) {
|
||||
if (items.size() < inventorySize) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (items.size() < inventorySize) {
|
||||
items.add(item);
|
||||
System.out.println(Thread.currentThread()
|
||||
+ ": items.size()=" + items.size()
|
||||
+ ", inventorySize=" + inventorySize);
|
||||
return true;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public Inventory(int inventorySize) {
|
||||
this.inventorySize = inventorySize;
|
||||
this.items = new ArrayList<>(inventorySize);
|
||||
this.lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
public boolean addItem(Item item) {
|
||||
if (items.size() < inventorySize) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (items.size() < inventorySize) {
|
||||
items.add(item);
|
||||
System.out.println(Thread.currentThread() + ": items.size()=" + items.size()
|
||||
+ ", inventorySize=" + inventorySize);
|
||||
return true;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ package com.iluwatar.doublechecked.locking;
|
||||
*
|
||||
*/
|
||||
public class Item {
|
||||
|
||||
private String name;
|
||||
private int level;
|
||||
|
||||
private String name;
|
||||
private int level;
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import com.iluwatar.doublechecked.locking.App;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -5,46 +5,50 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* When a message with a parameter is sent to an object, the resultant behaviour is defined by the
|
||||
* implementation of that method in the receiver. Sometimes the behaviour must also be determined
|
||||
* by the type of the parameter.
|
||||
* When a message with a parameter is sent to an object, the resultant behaviour is defined by the
|
||||
* implementation of that method in the receiver. Sometimes the behaviour must also be determined by
|
||||
* the type of the parameter.
|
||||
* <p>
|
||||
* One way to implement this would be to create multiple instanceof-checks for the methods parameter.
|
||||
* However, this creates a maintenance issue. When new types are added we would also need to change
|
||||
* the method's implementation and add a new instanceof-check. This violates the single responsibility
|
||||
* principle - a class should have only one reason to change.
|
||||
* One way to implement this would be to create multiple instanceof-checks for the methods
|
||||
* parameter. However, this creates a maintenance issue. When new types are added we would also need
|
||||
* to change the method's implementation and add a new instanceof-check. This violates the single
|
||||
* responsibility principle - a class should have only one reason to change.
|
||||
* <p>
|
||||
* Instead of the instanceof-checks a better way is to make another virtual call on the parameter
|
||||
* object. This way new functionality can be easily added without the need to modify existing
|
||||
* implementation (open-closed principle).
|
||||
* <p>
|
||||
* In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other. Each
|
||||
* object has its own coordinates which are checked against the other objects' coordinates. If
|
||||
* In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other.
|
||||
* Each object has its own coordinates which are checked against the other objects' coordinates. If
|
||||
* there is an overlap, then the objects collide utilizing the Double Dispatch pattern.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main( String[] args ) {
|
||||
// initialize game objects and print their status
|
||||
List<GameObject> objects = new ArrayList<>();
|
||||
objects.add(new FlamingAsteroid(0, 0, 5, 5));
|
||||
objects.add(new SpaceStationMir(1, 1, 2, 2));
|
||||
objects.add(new Meteoroid(10, 10, 15, 15));
|
||||
objects.add(new SpaceStationIss(12, 12, 14, 14));
|
||||
objects.stream().forEach(o -> System.out.println(o));
|
||||
System.out.println("");
|
||||
|
||||
// collision check
|
||||
objects.stream().forEach(o1 -> objects.stream().forEach(o2 -> { if (o1 != o2 && o1.intersectsWith(o2)) o1.collision(o2); } ));
|
||||
System.out.println("");
|
||||
|
||||
// output eventual object statuses
|
||||
objects.stream().forEach(o -> System.out.println(o));
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// initialize game objects and print their status
|
||||
List<GameObject> objects = new ArrayList<>();
|
||||
objects.add(new FlamingAsteroid(0, 0, 5, 5));
|
||||
objects.add(new SpaceStationMir(1, 1, 2, 2));
|
||||
objects.add(new Meteoroid(10, 10, 15, 15));
|
||||
objects.add(new SpaceStationIss(12, 12, 14, 14));
|
||||
objects.stream().forEach(o -> System.out.println(o));
|
||||
System.out.println("");
|
||||
|
||||
// collision check
|
||||
objects.stream().forEach(o1 -> objects.stream().forEach(o2 -> {
|
||||
if (o1 != o2 && o1.intersectsWith(o2))
|
||||
o1.collision(o2);
|
||||
}));
|
||||
System.out.println("");
|
||||
|
||||
// output eventual object statuses
|
||||
objects.stream().forEach(o -> System.out.println(o));
|
||||
System.out.println("");
|
||||
}
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ package com.iluwatar.doubledispatch;
|
||||
*/
|
||||
public class FlamingAsteroid extends Meteoroid {
|
||||
|
||||
public FlamingAsteroid(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
setOnFire(true);
|
||||
}
|
||||
public FlamingAsteroid(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
setOnFire(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
}
|
||||
|
@ -2,48 +2,47 @@ package com.iluwatar.doubledispatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* Game objects have coordinates and some
|
||||
* other status information.
|
||||
* Game objects have coordinates and some other status information.
|
||||
*
|
||||
*/
|
||||
public abstract class GameObject extends Rectangle {
|
||||
|
||||
private boolean damaged;
|
||||
private boolean onFire;
|
||||
|
||||
public GameObject(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s at %s damaged=%b onFire=%b", this.getClass().getSimpleName(),
|
||||
super.toString(), isDamaged(), isOnFire());
|
||||
}
|
||||
|
||||
public boolean isOnFire() {
|
||||
return onFire;
|
||||
}
|
||||
|
||||
public void setOnFire(boolean onFire) {
|
||||
this.onFire = onFire;
|
||||
}
|
||||
|
||||
public boolean isDamaged() {
|
||||
return damaged;
|
||||
}
|
||||
|
||||
public void setDamaged(boolean damaged) {
|
||||
this.damaged = damaged;
|
||||
}
|
||||
|
||||
public abstract void collision(GameObject gameObject);
|
||||
|
||||
public abstract void collisionResolve(FlamingAsteroid asteroid);
|
||||
|
||||
public abstract void collisionResolve(Meteoroid meteoroid);
|
||||
private boolean damaged;
|
||||
private boolean onFire;
|
||||
|
||||
public abstract void collisionResolve(SpaceStationMir mir);
|
||||
public GameObject(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public abstract void collisionResolve(SpaceStationIss iss);
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s at %s damaged=%b onFire=%b", this.getClass().getSimpleName(),
|
||||
super.toString(), isDamaged(), isOnFire());
|
||||
}
|
||||
|
||||
public boolean isOnFire() {
|
||||
return onFire;
|
||||
}
|
||||
|
||||
public void setOnFire(boolean onFire) {
|
||||
this.onFire = onFire;
|
||||
}
|
||||
|
||||
public boolean isDamaged() {
|
||||
return damaged;
|
||||
}
|
||||
|
||||
public void setDamaged(boolean damaged) {
|
||||
this.damaged = damaged;
|
||||
}
|
||||
|
||||
public abstract void collision(GameObject gameObject);
|
||||
|
||||
public abstract void collisionResolve(FlamingAsteroid asteroid);
|
||||
|
||||
public abstract void collisionResolve(Meteoroid meteoroid);
|
||||
|
||||
public abstract void collisionResolve(SpaceStationMir mir);
|
||||
|
||||
public abstract void collisionResolve(SpaceStationIss iss);
|
||||
}
|
||||
|
@ -7,32 +7,36 @@ package com.iluwatar.doubledispatch;
|
||||
*/
|
||||
public class Meteoroid extends GameObject {
|
||||
|
||||
public Meteoroid(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
public Meteoroid(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(FlamingAsteroid asteroid) {
|
||||
System.out.println(String.format("%s hits %s.", asteroid.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(FlamingAsteroid asteroid) {
|
||||
System.out.println(String.format("%s hits %s.", asteroid.getClass().getSimpleName(), this
|
||||
.getClass().getSimpleName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(Meteoroid meteoroid) {
|
||||
System.out.println(String.format("%s hits %s.", meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(Meteoroid meteoroid) {
|
||||
System.out.println(String.format("%s hits %s.", meteoroid.getClass().getSimpleName(), this
|
||||
.getClass().getSimpleName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationMir mir) {
|
||||
System.out.println(String.format("%s hits %s.", mir.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationMir mir) {
|
||||
System.out.println(String.format("%s hits %s.", mir.getClass().getSimpleName(), this.getClass()
|
||||
.getSimpleName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationIss iss) {
|
||||
System.out.println(String.format("%s hits %s.", iss.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationIss iss) {
|
||||
System.out.println(String.format("%s hits %s.", iss.getClass().getSimpleName(), this.getClass()
|
||||
.getSimpleName()));
|
||||
}
|
||||
}
|
||||
|
@ -2,43 +2,46 @@ package com.iluwatar.doubledispatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* Rectangle has coordinates and can be checked for overlap against
|
||||
* other Rectangles.
|
||||
* Rectangle has coordinates and can be checked for overlap against other Rectangles.
|
||||
*
|
||||
*/
|
||||
public class Rectangle {
|
||||
|
||||
private int left;
|
||||
private int top;
|
||||
private int right;
|
||||
private int bottom;
|
||||
private int left;
|
||||
private int top;
|
||||
private int right;
|
||||
private int bottom;
|
||||
|
||||
public Rectangle(int left, int top, int right, int bottom) {
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public int getLeft() {
|
||||
return left;
|
||||
}
|
||||
public int getTop() {
|
||||
return top;
|
||||
}
|
||||
public int getRight() {
|
||||
return right;
|
||||
}
|
||||
public int getBottom() {
|
||||
return bottom;
|
||||
}
|
||||
|
||||
boolean intersectsWith(Rectangle r) {
|
||||
return !(r.getLeft() > getRight() || r.getRight() < getLeft() || r.getTop() > getBottom() || r.getBottom() < getTop());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%d,%d,%d,%d]", getLeft(), getTop(), getRight(), getBottom());
|
||||
}
|
||||
public Rectangle(int left, int top, int right, int bottom) {
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public int getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public int getTop() {
|
||||
return top;
|
||||
}
|
||||
|
||||
public int getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public int getBottom() {
|
||||
return bottom;
|
||||
}
|
||||
|
||||
boolean intersectsWith(Rectangle r) {
|
||||
return !(r.getLeft() > getRight() || r.getRight() < getLeft() || r.getTop() > getBottom() || r
|
||||
.getBottom() < getTop());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%d,%d,%d,%d]", getLeft(), getTop(), getRight(), getBottom());
|
||||
}
|
||||
}
|
||||
|
@ -7,12 +7,12 @@ package com.iluwatar.doubledispatch;
|
||||
*/
|
||||
public class SpaceStationIss extends SpaceStationMir {
|
||||
|
||||
public SpaceStationIss(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
public SpaceStationIss(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
}
|
||||
|
@ -7,45 +7,42 @@ package com.iluwatar.doubledispatch;
|
||||
*/
|
||||
public class SpaceStationMir extends GameObject {
|
||||
|
||||
public SpaceStationMir(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
public SpaceStationMir(int left, int top, int right, int bottom) {
|
||||
super(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
@Override
|
||||
public void collision(GameObject gameObject) {
|
||||
gameObject.collisionResolve(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(FlamingAsteroid asteroid) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged! %s is set on fire!",
|
||||
asteroid.getClass().getSimpleName(), this.getClass().getSimpleName(),
|
||||
this.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
setOnFire(true);
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(FlamingAsteroid asteroid) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged! %s is set on fire!", asteroid
|
||||
.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass()
|
||||
.getSimpleName(), this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
setOnFire(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(Meteoroid meteoroid) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged!",
|
||||
meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName(),
|
||||
this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(Meteoroid meteoroid) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged!", meteoroid.getClass()
|
||||
.getSimpleName(), this.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationMir mir) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged!",
|
||||
mir.getClass().getSimpleName(), this.getClass().getSimpleName(),
|
||||
this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationMir mir) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged!", mir.getClass().getSimpleName(),
|
||||
this.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationIss iss) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged!",
|
||||
iss.getClass().getSimpleName(), this.getClass().getSimpleName(),
|
||||
this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
}
|
||||
@Override
|
||||
public void collisionResolve(SpaceStationIss iss) {
|
||||
System.out.println(String.format("%s hits %s. %s is damaged!", iss.getClass().getSimpleName(),
|
||||
this.getClass().getSimpleName(), this.getClass().getSimpleName()));
|
||||
setDamaged(true);
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ import com.iluwatar.doubledispatch.App;
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ import com.iluwatar.doubledispatch.Rectangle;
|
||||
*/
|
||||
public class RectangleTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Assert.assertTrue(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(0,0,1,1)));
|
||||
Assert.assertTrue(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(-1,-5,7,8)));
|
||||
Assert.assertFalse(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(2,2,3,3)));
|
||||
Assert.assertFalse(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(-2,-2,-1,-1)));
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
Assert.assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(0, 0, 1, 1)));
|
||||
Assert.assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-1, -5, 7, 8)));
|
||||
Assert.assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(2, 2, 3, 3)));
|
||||
Assert.assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-2, -2, -1, -1)));
|
||||
}
|
||||
}
|
||||
|
@ -5,39 +5,40 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* A system with lots of objects can lead to complexities when a client wants to subscribe
|
||||
* to events. The client has to find and register for each object individually, if each
|
||||
* object has multiple events then each event requires a separate subscription.
|
||||
* A system with lots of objects can lead to complexities when a client wants to subscribe to
|
||||
* events. The client has to find and register for each object individually, if each object has
|
||||
* multiple events then each event requires a separate subscription.
|
||||
* <p>
|
||||
* An Event Aggregator acts as a single source of events for many objects. It registers
|
||||
* for all the events of the many objects allowing clients to register with just the aggregator.
|
||||
* An Event Aggregator acts as a single source of events for many objects. It registers for all the
|
||||
* events of the many objects allowing clients to register with just the aggregator.
|
||||
* <p>
|
||||
* In the example {@link LordBaelish}, {@link LordVarys} and {@link Scout} deliver events to
|
||||
* {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events
|
||||
* to {@link KingJoffrey}.
|
||||
* {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events to
|
||||
* {@link KingJoffrey}.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
KingJoffrey kingJoffrey = new KingJoffrey();
|
||||
KingsHand kingsHand = new KingsHand(kingJoffrey);
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
List<EventEmitter> emitters = new ArrayList<>();
|
||||
emitters.add(kingsHand);
|
||||
emitters.add(new LordBaelish(kingsHand));
|
||||
emitters.add(new LordVarys(kingsHand));
|
||||
emitters.add(new Scout(kingsHand));
|
||||
|
||||
for (Weekday day: Weekday.values()) {
|
||||
for (EventEmitter emitter: emitters) {
|
||||
emitter.timePasses(day);
|
||||
}
|
||||
}
|
||||
}
|
||||
KingJoffrey kingJoffrey = new KingJoffrey();
|
||||
KingsHand kingsHand = new KingsHand(kingJoffrey);
|
||||
|
||||
List<EventEmitter> emitters = new ArrayList<>();
|
||||
emitters.add(kingsHand);
|
||||
emitters.add(new LordBaelish(kingsHand));
|
||||
emitters.add(new LordVarys(kingsHand));
|
||||
emitters.add(new Scout(kingsHand));
|
||||
|
||||
for (Weekday day : Weekday.values()) {
|
||||
for (EventEmitter emitter : emitters) {
|
||||
emitter.timePasses(day);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,15 +7,16 @@ package com.iluwatar.event.aggregator;
|
||||
*/
|
||||
public enum Event {
|
||||
|
||||
STARK_SIGHTED("Stark sighted"), WARSHIPS_APPROACHING("Warships approaching"), TRAITOR_DETECTED("Traitor detected");
|
||||
|
||||
private String description;
|
||||
|
||||
Event(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
STARK_SIGHTED("Stark sighted"), WARSHIPS_APPROACHING("Warships approaching"), TRAITOR_DETECTED(
|
||||
"Traitor detected");
|
||||
|
||||
private String description;
|
||||
|
||||
Event(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
@ -10,26 +10,26 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class EventEmitter {
|
||||
|
||||
private List<EventObserver> observers;
|
||||
private List<EventObserver> observers;
|
||||
|
||||
public EventEmitter() {
|
||||
observers = new LinkedList<>();
|
||||
}
|
||||
public EventEmitter() {
|
||||
observers = new LinkedList<>();
|
||||
}
|
||||
|
||||
public EventEmitter(EventObserver obs) {
|
||||
this();
|
||||
registerObserver(obs);
|
||||
}
|
||||
|
||||
public void registerObserver(EventObserver obs) {
|
||||
observers.add(obs);
|
||||
}
|
||||
|
||||
protected void notifyObservers(Event e) {
|
||||
for (EventObserver obs: observers) {
|
||||
obs.onEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void timePasses(Weekday day);
|
||||
public EventEmitter(EventObserver obs) {
|
||||
this();
|
||||
registerObserver(obs);
|
||||
}
|
||||
|
||||
public void registerObserver(EventObserver obs) {
|
||||
observers.add(obs);
|
||||
}
|
||||
|
||||
protected void notifyObservers(Event e) {
|
||||
for (EventObserver obs : observers) {
|
||||
obs.onEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void timePasses(Weekday day);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ package com.iluwatar.event.aggregator;
|
||||
*
|
||||
*/
|
||||
public interface EventObserver {
|
||||
|
||||
void onEvent(Event e);
|
||||
|
||||
void onEvent(Event e);
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ package com.iluwatar.event.aggregator;
|
||||
*/
|
||||
public class KingJoffrey implements EventObserver {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event e) {
|
||||
System.out.println("Received event from the King's Hand: " + e.toString());
|
||||
}
|
||||
@Override
|
||||
public void onEvent(Event e) {
|
||||
System.out.println("Received event from the King's Hand: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
@ -2,27 +2,26 @@ package com.iluwatar.event.aggregator;
|
||||
|
||||
/**
|
||||
*
|
||||
* KingsHand observes events from multiple sources and delivers them
|
||||
* to listeners.
|
||||
* KingsHand observes events from multiple sources and delivers them to listeners.
|
||||
*
|
||||
*/
|
||||
public class KingsHand extends EventEmitter implements EventObserver {
|
||||
|
||||
public KingsHand() {
|
||||
super();
|
||||
}
|
||||
public KingsHand() {
|
||||
super();
|
||||
}
|
||||
|
||||
public KingsHand(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event e) {
|
||||
notifyObservers(e);
|
||||
}
|
||||
public KingsHand(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
// NOP
|
||||
}
|
||||
@Override
|
||||
public void onEvent(Event e) {
|
||||
notifyObservers(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,19 @@ package com.iluwatar.event.aggregator;
|
||||
*
|
||||
*/
|
||||
public class LordBaelish extends EventEmitter {
|
||||
|
||||
public LordBaelish() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LordBaelish(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
if (day.equals(Weekday.FRIDAY)) {
|
||||
notifyObservers(Event.STARK_SIGHTED);
|
||||
}
|
||||
}
|
||||
public LordBaelish() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LordBaelish(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
if (day.equals(Weekday.FRIDAY)) {
|
||||
notifyObservers(Event.STARK_SIGHTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,19 @@ package com.iluwatar.event.aggregator;
|
||||
*
|
||||
*/
|
||||
public class LordVarys extends EventEmitter {
|
||||
|
||||
public LordVarys() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LordVarys(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
if (day.equals(Weekday.SATURDAY)) {
|
||||
notifyObservers(Event.TRAITOR_DETECTED);
|
||||
}
|
||||
}
|
||||
public LordVarys() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LordVarys(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
if (day.equals(Weekday.SATURDAY)) {
|
||||
notifyObservers(Event.TRAITOR_DETECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,19 @@ package com.iluwatar.event.aggregator;
|
||||
*
|
||||
*/
|
||||
public class Scout extends EventEmitter {
|
||||
|
||||
public Scout() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Scout(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
if (day.equals(Weekday.TUESDAY)) {
|
||||
notifyObservers(Event.WARSHIPS_APPROACHING);
|
||||
}
|
||||
}
|
||||
public Scout() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Scout(EventObserver obs) {
|
||||
super(obs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timePasses(Weekday day) {
|
||||
if (day.equals(Weekday.TUESDAY)) {
|
||||
notifyObservers(Event.WARSHIPS_APPROACHING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,16 +6,17 @@ package com.iluwatar.event.aggregator;
|
||||
*
|
||||
*/
|
||||
public enum Weekday {
|
||||
|
||||
MONDAY("Monday"), TUESDAY("Tuesday"), WEDNESDAY("Wednesday"), THURSDAY("Thursday"), FRIDAY("Friday"), SATURDAY("Saturday"), SUNDAY("Sunday");
|
||||
|
||||
private String description;
|
||||
|
||||
Weekday(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
MONDAY("Monday"), TUESDAY("Tuesday"), WEDNESDAY("Wednesday"), THURSDAY("Thursday"), FRIDAY(
|
||||
"Friday"), SATURDAY("Saturday"), SUNDAY("Sunday");
|
||||
|
||||
private String description;
|
||||
|
||||
Weekday(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
package com.iluwatar.event.aggregator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.iluwatar.event.aggregator.App;
|
||||
@ -10,9 +11,9 @@ import com.iluwatar.event.aggregator.App;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -4,32 +4,33 @@ import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The Execute Around idiom specifies some code to be executed before and after
|
||||
* a method. Typically the idiom is used when the API has methods to be executed in
|
||||
* pairs, such as resource allocation/deallocation or lock acquisition/release.
|
||||
* The Execute Around idiom specifies some code to be executed before and after a method. Typically
|
||||
* the idiom is used when the API has methods to be executed in pairs, such as resource
|
||||
* allocation/deallocation or lock acquisition/release.
|
||||
* <p>
|
||||
* In this example, we have {@link SimpleFileWriter} class that opens and closes the file
|
||||
* for the user. The user specifies only what to do with the file by providing the
|
||||
* {@link FileWriterAction} implementation.
|
||||
* In this example, we have {@link SimpleFileWriter} class that opens and closes the file for the
|
||||
* user. The user specifies only what to do with the file by providing the {@link FileWriterAction}
|
||||
* implementation.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main( String[] args ) throws IOException {
|
||||
|
||||
new SimpleFileWriter("testfile.txt", new FileWriterAction() {
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
@Override
|
||||
public void writeFile(FileWriter writer) throws IOException {
|
||||
writer.write("Hello");
|
||||
writer.append(" ");
|
||||
writer.append("there!");
|
||||
}
|
||||
});
|
||||
}
|
||||
new SimpleFileWriter("testfile.txt", new FileWriterAction() {
|
||||
|
||||
@Override
|
||||
public void writeFile(FileWriter writer) throws IOException {
|
||||
writer.write("Hello");
|
||||
writer.append(" ");
|
||||
writer.append("there!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,6 @@ import java.io.IOException;
|
||||
*/
|
||||
public interface FileWriterAction {
|
||||
|
||||
void writeFile(FileWriter writer) throws IOException;
|
||||
|
||||
void writeFile(FileWriter writer) throws IOException;
|
||||
|
||||
}
|
||||
|
@ -5,19 +5,18 @@ import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* SimpleFileWriter handles opening and closing file for the user. The user
|
||||
* only has to specify what to do with the file resource through {@link FileWriterAction}
|
||||
* parameter.
|
||||
* SimpleFileWriter handles opening and closing file for the user. The user only has to specify what
|
||||
* to do with the file resource through {@link FileWriterAction} parameter.
|
||||
*
|
||||
*/
|
||||
public class SimpleFileWriter {
|
||||
|
||||
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
|
||||
FileWriter writer = new FileWriter(filename);
|
||||
try {
|
||||
action.writeFile(writer);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
|
||||
FileWriter writer = new FileWriter(filename);
|
||||
try {
|
||||
action.writeFile(writer);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,17 +15,17 @@ import com.iluwatar.execute.around.App;
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void cleanup() {
|
||||
File file = new File("testfile.txt");
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void cleanup() {
|
||||
File file = new File("testfile.txt");
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
@ -2,27 +2,28 @@ package com.iluwatar.facade;
|
||||
|
||||
/**
|
||||
*
|
||||
* The Facade design pattern is often used when a system is very complex or difficult
|
||||
* to understand because the system has a large number of interdependent classes or
|
||||
* its source code is unavailable. This pattern hides the complexities of the larger
|
||||
* system and provides a simpler interface to the client. It typically involves a single
|
||||
* wrapper class which contains a set of members required by client. These members access
|
||||
* the system on behalf of the facade client and hide the implementation details.
|
||||
* The Facade design pattern is often used when a system is very complex or difficult to understand
|
||||
* because the system has a large number of interdependent classes or its source code is
|
||||
* unavailable. This pattern hides the complexities of the larger system and provides a simpler
|
||||
* interface to the client. It typically involves a single wrapper class which contains a set of
|
||||
* members required by client. These members access the system on behalf of the facade client and
|
||||
* hide the implementation details.
|
||||
* <p>
|
||||
* In this example the Facade is ({@link DwarvenGoldmineFacade}) and it provides a simpler
|
||||
* interface to the goldmine subsystem.
|
||||
* In this example the Facade is ({@link DwarvenGoldmineFacade}) and it provides a simpler interface
|
||||
* to the goldmine subsystem.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
DwarvenGoldmineFacade facade = new DwarvenGoldmineFacade();
|
||||
facade.startNewDay();
|
||||
facade.digOutGold();
|
||||
facade.endDay();
|
||||
}
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
DwarvenGoldmineFacade facade = new DwarvenGoldmineFacade();
|
||||
facade.startNewDay();
|
||||
facade.digOutGold();
|
||||
facade.endDay();
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,13 @@ package com.iluwatar.facade;
|
||||
*/
|
||||
public class DwarvenCartOperator extends DwarvenMineWorker {
|
||||
|
||||
@Override
|
||||
public void work() {
|
||||
System.out.println(name() + " moves gold chunks out of the mine.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Dwarf cart operator";
|
||||
}
|
||||
@Override
|
||||
public void work() {
|
||||
System.out.println(name() + " moves gold chunks out of the mine.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Dwarf cart operator";
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,13 @@ package com.iluwatar.facade;
|
||||
*/
|
||||
public class DwarvenGoldDigger extends DwarvenMineWorker {
|
||||
|
||||
@Override
|
||||
public void work() {
|
||||
System.out.println(name() + " digs for gold.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Dwarf gold digger";
|
||||
}
|
||||
@Override
|
||||
public void work() {
|
||||
System.out.println(name() + " digs for gold.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Dwarf gold digger";
|
||||
}
|
||||
}
|
||||
|
@ -6,40 +6,39 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* DwarvenGoldmineFacade provides a single interface
|
||||
* through which users can operate the subsystems.
|
||||
* DwarvenGoldmineFacade provides a single interface through which users can operate the subsystems.
|
||||
*
|
||||
* This makes the goldmine easier to operate and
|
||||
* cuts the dependencies from the goldmine user to
|
||||
* the subsystems.
|
||||
* This makes the goldmine easier to operate and cuts the dependencies from the goldmine user to the
|
||||
* subsystems.
|
||||
*
|
||||
*/
|
||||
public class DwarvenGoldmineFacade {
|
||||
|
||||
private final List<DwarvenMineWorker> workers;
|
||||
private final List<DwarvenMineWorker> workers;
|
||||
|
||||
public DwarvenGoldmineFacade() {
|
||||
workers = new ArrayList<>();
|
||||
workers.add(new DwarvenGoldDigger());
|
||||
workers.add(new DwarvenCartOperator());
|
||||
workers.add(new DwarvenTunnelDigger());
|
||||
}
|
||||
public DwarvenGoldmineFacade() {
|
||||
workers = new ArrayList<>();
|
||||
workers.add(new DwarvenGoldDigger());
|
||||
workers.add(new DwarvenCartOperator());
|
||||
workers.add(new DwarvenTunnelDigger());
|
||||
}
|
||||
|
||||
public void startNewDay() {
|
||||
makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);
|
||||
}
|
||||
public void startNewDay() {
|
||||
makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);
|
||||
}
|
||||
|
||||
public void digOutGold() {
|
||||
makeActions(workers, DwarvenMineWorker.Action.WORK);
|
||||
}
|
||||
public void digOutGold() {
|
||||
makeActions(workers, DwarvenMineWorker.Action.WORK);
|
||||
}
|
||||
|
||||
public void endDay() {
|
||||
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
|
||||
}
|
||||
public void endDay() {
|
||||
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
|
||||
}
|
||||
|
||||
private void makeActions(Collection<DwarvenMineWorker> workers, DwarvenMineWorker.Action... actions) {
|
||||
for (DwarvenMineWorker worker : workers) {
|
||||
worker.action(actions);
|
||||
}
|
||||
private void makeActions(Collection<DwarvenMineWorker> workers,
|
||||
DwarvenMineWorker.Action... actions) {
|
||||
for (DwarvenMineWorker worker : workers) {
|
||||
worker.action(actions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,56 +7,56 @@ package com.iluwatar.facade;
|
||||
*/
|
||||
public abstract class DwarvenMineWorker {
|
||||
|
||||
public void goToSleep() {
|
||||
System.out.println(name() + " goes to sleep.");
|
||||
}
|
||||
public void goToSleep() {
|
||||
System.out.println(name() + " goes to sleep.");
|
||||
}
|
||||
|
||||
public void wakeUp() {
|
||||
System.out.println(name() + " wakes up.");
|
||||
}
|
||||
public void wakeUp() {
|
||||
System.out.println(name() + " wakes up.");
|
||||
}
|
||||
|
||||
public void goHome() {
|
||||
System.out.println(name() + " goes home.");
|
||||
}
|
||||
public void goHome() {
|
||||
System.out.println(name() + " goes home.");
|
||||
}
|
||||
|
||||
public void goToMine() {
|
||||
System.out.println(name() + " goes to the mine.");
|
||||
}
|
||||
public void goToMine() {
|
||||
System.out.println(name() + " goes to the mine.");
|
||||
}
|
||||
|
||||
private void action(Action action) {
|
||||
switch (action) {
|
||||
case GO_TO_SLEEP:
|
||||
goToSleep();
|
||||
break;
|
||||
case WAKE_UP:
|
||||
wakeUp();
|
||||
break;
|
||||
case GO_HOME:
|
||||
goHome();
|
||||
break;
|
||||
case GO_TO_MINE:
|
||||
goToMine();
|
||||
break;
|
||||
case WORK:
|
||||
work();
|
||||
break;
|
||||
default:
|
||||
System.out.println("Undefined action");
|
||||
break;
|
||||
}
|
||||
private void action(Action action) {
|
||||
switch (action) {
|
||||
case GO_TO_SLEEP:
|
||||
goToSleep();
|
||||
break;
|
||||
case WAKE_UP:
|
||||
wakeUp();
|
||||
break;
|
||||
case GO_HOME:
|
||||
goHome();
|
||||
break;
|
||||
case GO_TO_MINE:
|
||||
goToMine();
|
||||
break;
|
||||
case WORK:
|
||||
work();
|
||||
break;
|
||||
default:
|
||||
System.out.println("Undefined action");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void action(Action... actions) {
|
||||
for (Action action : actions) {
|
||||
action(action);
|
||||
}
|
||||
public void action(Action... actions) {
|
||||
for (Action action : actions) {
|
||||
action(action);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void work();
|
||||
public abstract void work();
|
||||
|
||||
public abstract String name();
|
||||
public abstract String name();
|
||||
|
||||
static enum Action {
|
||||
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
||||
}
|
||||
static enum Action {
|
||||
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,13 @@ package com.iluwatar.facade;
|
||||
*/
|
||||
public class DwarvenTunnelDigger extends DwarvenMineWorker {
|
||||
|
||||
@Override
|
||||
public void work() {
|
||||
System.out.println(name() + " creates another promising tunnel.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Dwarven tunnel digger";
|
||||
}
|
||||
@Override
|
||||
public void work() {
|
||||
System.out.println(name() + " creates another promising tunnel.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Dwarven tunnel digger";
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import com.iluwatar.facade.App;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -2,39 +2,39 @@ package com.iluwatar.factory.method;
|
||||
|
||||
/**
|
||||
*
|
||||
* The Factory Method is a creational design pattern which uses factory methods to deal
|
||||
* with the problem of creating objects without specifying the exact class of object
|
||||
* that will be created. This is done by creating objects via calling a factory
|
||||
* method either specified in an interface and implemented by child classes, or implemented
|
||||
* in a base class and optionally overridden by derived classes—rather than by calling a
|
||||
* constructor.
|
||||
* The Factory Method is a creational design pattern which uses factory methods to deal with the
|
||||
* problem of creating objects without specifying the exact class of object that will be created.
|
||||
* This is done by creating objects via calling a factory method either specified in an interface
|
||||
* and implemented by child classes, or implemented in a base class and optionally overridden by
|
||||
* derived classes—rather than by calling a constructor.
|
||||
* <p>
|
||||
* In this Factory Method example we have an interface ({@link Blacksmith}) with a method for
|
||||
* creating objects ({@link Blacksmith#manufactureWeapon}). The concrete subclasses
|
||||
* ({@link OrcBlacksmith}, {@link ElfBlacksmith}) then override the method to produce
|
||||
* objects of their liking.
|
||||
* creating objects ({@link Blacksmith#manufactureWeapon}). The concrete subclasses (
|
||||
* {@link OrcBlacksmith}, {@link ElfBlacksmith}) then override the method to produce objects of
|
||||
* their liking.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Blacksmith blacksmith;
|
||||
Weapon weapon;
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Blacksmith blacksmith;
|
||||
Weapon weapon;
|
||||
|
||||
blacksmith = new OrcBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
System.out.println(weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
System.out.println(weapon);
|
||||
blacksmith = new OrcBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
System.out.println(weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
System.out.println(weapon);
|
||||
|
||||
blacksmith = new ElfBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SHORT_SWORD);
|
||||
System.out.println(weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
System.out.println(weapon);
|
||||
}
|
||||
blacksmith = new ElfBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SHORT_SWORD);
|
||||
System.out.println(weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
System.out.println(weapon);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ package com.iluwatar.factory.method;
|
||||
*/
|
||||
public interface Blacksmith {
|
||||
|
||||
Weapon manufactureWeapon(WeaponType weaponType);
|
||||
Weapon manufactureWeapon(WeaponType weaponType);
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ package com.iluwatar.factory.method;
|
||||
*/
|
||||
public class ElfBlacksmith implements Blacksmith {
|
||||
|
||||
public Weapon manufactureWeapon(WeaponType weaponType) {
|
||||
return new ElfWeapon(weaponType);
|
||||
}
|
||||
public Weapon manufactureWeapon(WeaponType weaponType) {
|
||||
return new ElfWeapon(weaponType);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,15 +7,14 @@ package com.iluwatar.factory.method;
|
||||
*/
|
||||
public class ElfWeapon implements Weapon {
|
||||
|
||||
private WeaponType weaponType;
|
||||
private WeaponType weaponType;
|
||||
|
||||
public ElfWeapon(WeaponType weaponType) {
|
||||
this.weaponType = weaponType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Elven " + weaponType;
|
||||
}
|
||||
public ElfWeapon(WeaponType weaponType) {
|
||||
this.weaponType = weaponType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Elven " + weaponType;
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ package com.iluwatar.factory.method;
|
||||
*/
|
||||
public class OrcBlacksmith implements Blacksmith {
|
||||
|
||||
public Weapon manufactureWeapon(WeaponType weaponType) {
|
||||
return new OrcWeapon(weaponType);
|
||||
}
|
||||
|
||||
public Weapon manufactureWeapon(WeaponType weaponType) {
|
||||
return new OrcWeapon(weaponType);
|
||||
}
|
||||
}
|
||||
|
@ -7,15 +7,14 @@ package com.iluwatar.factory.method;
|
||||
*/
|
||||
public class OrcWeapon implements Weapon {
|
||||
|
||||
private WeaponType weaponType;
|
||||
private WeaponType weaponType;
|
||||
|
||||
public OrcWeapon(WeaponType weaponType) {
|
||||
this.weaponType = weaponType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Orcish " + weaponType;
|
||||
}
|
||||
public OrcWeapon(WeaponType weaponType) {
|
||||
this.weaponType = weaponType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Orcish " + weaponType;
|
||||
}
|
||||
}
|
||||
|
@ -7,16 +7,16 @@ package com.iluwatar.factory.method;
|
||||
*/
|
||||
public enum WeaponType {
|
||||
|
||||
SHORT_SWORD("short sword"), SPEAR("spear"), AXE("axe"), UNDEFINED("");
|
||||
SHORT_SWORD("short sword"), SPEAR("spear"), AXE("axe"), UNDEFINED("");
|
||||
|
||||
private String title;
|
||||
private String title;
|
||||
|
||||
WeaponType(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
WeaponType(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import com.iluwatar.factory.method.App;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,15 @@ import java.util.function.Predicate;
|
||||
import static java.lang.String.valueOf;
|
||||
|
||||
/**
|
||||
* The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API. Those
|
||||
* interfaces tend to mimic domain specific languages, so they can nearly be read as human languages.
|
||||
* The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API.
|
||||
* Those interfaces tend to mimic domain specific languages, so they can nearly be read as human
|
||||
* languages.
|
||||
* <p>
|
||||
* In this example two implementations of a {@link FluentIterable} interface are given. The
|
||||
* {@link SimpleFluentIterable} evaluates eagerly and would be too costly for real world applications.
|
||||
* The {@link LazyFluentIterable} is evaluated on termination. Their usage is demonstrated with a
|
||||
* simple number list that is filtered, transformed and collected. The result is printed afterwards.
|
||||
* {@link SimpleFluentIterable} evaluates eagerly and would be too costly for real world
|
||||
* applications. The {@link LazyFluentIterable} is evaluated on termination. Their usage is
|
||||
* demonstrated with a simple number list that is filtered, transformed and collected. The result is
|
||||
* printed afterwards.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
@ -25,11 +27,9 @@ public class App {
|
||||
public static void main(String[] args) {
|
||||
|
||||
List<Integer> integerList = new ArrayList<>();
|
||||
integerList.addAll(Arrays.asList(
|
||||
1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97,
|
||||
45, 23, 2, -68, 45
|
||||
));
|
||||
|
||||
integerList.addAll(Arrays.asList(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2,
|
||||
-68, 45));
|
||||
|
||||
prettyPrint("The initial list contains: ", integerList);
|
||||
|
||||
List<Integer> firstFiveNegatives =
|
||||
|
@ -7,13 +7,13 @@ package com.iluwatar.flux.action;
|
||||
*/
|
||||
public abstract class Action {
|
||||
|
||||
private ActionType type;
|
||||
|
||||
public Action(ActionType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public ActionType getType() {
|
||||
return type;
|
||||
}
|
||||
private ActionType type;
|
||||
|
||||
public Action(ActionType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public ActionType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ package com.iluwatar.flux.action;
|
||||
*/
|
||||
public enum ActionType {
|
||||
|
||||
MENU_ITEM_SELECTED, CONTENT_CHANGED;
|
||||
|
||||
MENU_ITEM_SELECTED, CONTENT_CHANGED;
|
||||
|
||||
}
|
||||
|
@ -6,17 +6,18 @@ package com.iluwatar.flux.action;
|
||||
*
|
||||
*/
|
||||
public enum Content {
|
||||
|
||||
PRODUCTS("Products - This page lists the company's products."), COMPANY("Company - This page displays information about the company.");
|
||||
|
||||
private String title;
|
||||
|
||||
private Content(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
PRODUCTS("Products - This page lists the company's products."), COMPANY(
|
||||
"Company - This page displays information about the company.");
|
||||
|
||||
private String title;
|
||||
|
||||
private Content(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ package com.iluwatar.flux.action;
|
||||
*/
|
||||
public class ContentAction extends Action {
|
||||
|
||||
private Content content;
|
||||
private Content content;
|
||||
|
||||
public ContentAction(Content content) {
|
||||
super(ActionType.CONTENT_CHANGED);
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Content getContent() {
|
||||
return content;
|
||||
}
|
||||
public ContentAction(Content content) {
|
||||
super(ActionType.CONTENT_CHANGED);
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Content getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ package com.iluwatar.flux.action;
|
||||
*/
|
||||
public class MenuAction extends Action {
|
||||
|
||||
private MenuItem menuItem;
|
||||
private MenuItem menuItem;
|
||||
|
||||
public MenuAction(MenuItem menuItem) {
|
||||
super(ActionType.MENU_ITEM_SELECTED);
|
||||
this.menuItem = menuItem;
|
||||
}
|
||||
|
||||
public MenuItem getMenuItem() {
|
||||
return menuItem;
|
||||
}
|
||||
public MenuAction(MenuItem menuItem) {
|
||||
super(ActionType.MENU_ITEM_SELECTED);
|
||||
this.menuItem = menuItem;
|
||||
}
|
||||
|
||||
public MenuItem getMenuItem() {
|
||||
return menuItem;
|
||||
}
|
||||
}
|
||||
|
@ -6,17 +6,17 @@ package com.iluwatar.flux.action;
|
||||
*
|
||||
*/
|
||||
public enum MenuItem {
|
||||
|
||||
HOME("Home"), PRODUCTS("Products"), COMPANY("Company");
|
||||
|
||||
private String title;
|
||||
|
||||
MenuItem(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
HOME("Home"), PRODUCTS("Products"), COMPANY("Company");
|
||||
|
||||
private String title;
|
||||
|
||||
MenuItem(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
@ -9,43 +9,45 @@ import com.iluwatar.flux.view.MenuView;
|
||||
|
||||
/**
|
||||
*
|
||||
* Flux is the application architecture that Facebook uses for building client-side web
|
||||
* applications. Flux eschews MVC in favor of a unidirectional data flow. When a user interacts with
|
||||
* a React view, the view propagates an action through a central dispatcher, to the various stores that
|
||||
* hold the application's data and business logic, which updates all of the views that are affected.
|
||||
* Flux is the application architecture that Facebook uses for building client-side web
|
||||
* applications. Flux eschews MVC in favor of a unidirectional data flow. When a user interacts with
|
||||
* a React view, the view propagates an action through a central dispatcher, to the various stores
|
||||
* that hold the application's data and business logic, which updates all of the views that are
|
||||
* affected.
|
||||
* <p>
|
||||
* This example has two views: menu and content. They represent typical main menu and content area of
|
||||
* a web page. When menu item is clicked it triggers events through the dispatcher. The events are
|
||||
* received and handled by the stores updating their data as needed. The stores then notify the views
|
||||
* that they should rerender themselves.
|
||||
* This example has two views: menu and content. They represent typical main menu and content area
|
||||
* of a web page. When menu item is clicked it triggers events through the dispatcher. The events
|
||||
* are received and handled by the stores updating their data as needed. The stores then notify the
|
||||
* views that they should rerender themselves.
|
||||
* <p>
|
||||
* http://facebook.github.io/flux/docs/overview.html
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main( String[] args ) {
|
||||
|
||||
// initialize and wire the system
|
||||
MenuStore menuStore = new MenuStore();
|
||||
Dispatcher.getInstance().registerStore(menuStore);
|
||||
ContentStore contentStore = new ContentStore();
|
||||
Dispatcher.getInstance().registerStore(contentStore);
|
||||
MenuView menuView = new MenuView();
|
||||
menuStore.registerView(menuView);
|
||||
ContentView contentView = new ContentView();
|
||||
contentStore.registerView(contentView);
|
||||
|
||||
// render initial view
|
||||
menuView.render();
|
||||
contentView.render();
|
||||
|
||||
// user clicks another menu item
|
||||
// this triggers action dispatching and eventually causes views to render with new content
|
||||
menuView.itemClicked(MenuItem.COMPANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
// initialize and wire the system
|
||||
MenuStore menuStore = new MenuStore();
|
||||
Dispatcher.getInstance().registerStore(menuStore);
|
||||
ContentStore contentStore = new ContentStore();
|
||||
Dispatcher.getInstance().registerStore(contentStore);
|
||||
MenuView menuView = new MenuView();
|
||||
menuStore.registerView(menuView);
|
||||
ContentView contentView = new ContentView();
|
||||
contentStore.registerView(contentView);
|
||||
|
||||
// render initial view
|
||||
menuView.render();
|
||||
contentView.render();
|
||||
|
||||
// user clicks another menu item
|
||||
// this triggers action dispatching and eventually causes views to render with new content
|
||||
menuView.itemClicked(MenuItem.COMPANY);
|
||||
}
|
||||
}
|
||||
|
@ -16,37 +16,36 @@ import com.iluwatar.flux.store.Store;
|
||||
*
|
||||
*/
|
||||
public class Dispatcher {
|
||||
|
||||
private static Dispatcher instance = new Dispatcher();
|
||||
|
||||
private List<Store> stores = new LinkedList<>();
|
||||
|
||||
private Dispatcher() {
|
||||
}
|
||||
|
||||
public static Dispatcher getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void registerStore(Store store) {
|
||||
stores.add(store);
|
||||
}
|
||||
|
||||
public void menuItemSelected(MenuItem menuItem) {
|
||||
dispatchAction(new MenuAction(menuItem));
|
||||
switch (menuItem) {
|
||||
case HOME:
|
||||
case PRODUCTS:
|
||||
default:
|
||||
dispatchAction(new ContentAction(Content.PRODUCTS));
|
||||
break;
|
||||
case COMPANY:
|
||||
dispatchAction(new ContentAction(Content.COMPANY));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchAction(Action action) {
|
||||
stores.stream().forEach((store) -> store.onAction(action));
|
||||
}
|
||||
private static Dispatcher instance = new Dispatcher();
|
||||
|
||||
private List<Store> stores = new LinkedList<>();
|
||||
|
||||
private Dispatcher() {}
|
||||
|
||||
public static Dispatcher getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void registerStore(Store store) {
|
||||
stores.add(store);
|
||||
}
|
||||
|
||||
public void menuItemSelected(MenuItem menuItem) {
|
||||
dispatchAction(new MenuAction(menuItem));
|
||||
switch (menuItem) {
|
||||
case HOME:
|
||||
case PRODUCTS:
|
||||
default:
|
||||
dispatchAction(new ContentAction(Content.PRODUCTS));
|
||||
break;
|
||||
case COMPANY:
|
||||
dispatchAction(new ContentAction(Content.COMPANY));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchAction(Action action) {
|
||||
stores.stream().forEach((store) -> store.onAction(action));
|
||||
}
|
||||
}
|
||||
|
@ -12,18 +12,18 @@ import com.iluwatar.flux.action.ContentAction;
|
||||
*/
|
||||
public class ContentStore extends Store {
|
||||
|
||||
private Content content = Content.PRODUCTS;
|
||||
private Content content = Content.PRODUCTS;
|
||||
|
||||
@Override
|
||||
public void onAction(Action action) {
|
||||
if (action.getType().equals(ActionType.CONTENT_CHANGED)) {
|
||||
ContentAction contentAction = (ContentAction) action;
|
||||
content = contentAction.getContent();
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public Content getContent() {
|
||||
return content;
|
||||
}
|
||||
@Override
|
||||
public void onAction(Action action) {
|
||||
if (action.getType().equals(ActionType.CONTENT_CHANGED)) {
|
||||
ContentAction contentAction = (ContentAction) action;
|
||||
content = contentAction.getContent();
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public Content getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
@ -12,18 +12,18 @@ import com.iluwatar.flux.action.MenuItem;
|
||||
*/
|
||||
public class MenuStore extends Store {
|
||||
|
||||
private MenuItem selected = MenuItem.HOME;
|
||||
|
||||
@Override
|
||||
public void onAction(Action action) {
|
||||
if (action.getType().equals(ActionType.MENU_ITEM_SELECTED)) {
|
||||
MenuAction menuAction = (MenuAction) action;
|
||||
selected = menuAction.getMenuItem();
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public MenuItem getSelected() {
|
||||
return selected;
|
||||
}
|
||||
private MenuItem selected = MenuItem.HOME;
|
||||
|
||||
@Override
|
||||
public void onAction(Action action) {
|
||||
if (action.getType().equals(ActionType.MENU_ITEM_SELECTED)) {
|
||||
MenuAction menuAction = (MenuAction) action;
|
||||
selected = menuAction.getMenuItem();
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public MenuItem getSelected() {
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
@ -12,16 +12,16 @@ import com.iluwatar.flux.view.View;
|
||||
*
|
||||
*/
|
||||
public abstract class Store {
|
||||
|
||||
private List<View> views = new LinkedList<>();
|
||||
|
||||
public abstract void onAction(Action action);
|
||||
|
||||
public void registerView(View view) {
|
||||
views.add(view);
|
||||
}
|
||||
|
||||
protected void notifyChange() {
|
||||
views.stream().forEach((view) -> view.storeChanged(this));
|
||||
}
|
||||
private List<View> views = new LinkedList<>();
|
||||
|
||||
public abstract void onAction(Action action);
|
||||
|
||||
public void registerView(View view) {
|
||||
views.add(view);
|
||||
}
|
||||
|
||||
protected void notifyChange() {
|
||||
views.stream().forEach((view) -> view.storeChanged(this));
|
||||
}
|
||||
}
|
||||
|
@ -11,17 +11,17 @@ import com.iluwatar.flux.store.Store;
|
||||
*/
|
||||
public class ContentView implements View {
|
||||
|
||||
private Content content = Content.PRODUCTS;
|
||||
private Content content = Content.PRODUCTS;
|
||||
|
||||
@Override
|
||||
public void storeChanged(Store store) {
|
||||
ContentStore contentStore = (ContentStore) store;
|
||||
content = contentStore.getContent();
|
||||
render();
|
||||
}
|
||||
@Override
|
||||
public void storeChanged(Store store) {
|
||||
ContentStore contentStore = (ContentStore) store;
|
||||
content = contentStore.getContent();
|
||||
render();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
System.out.println(content.toString());
|
||||
}
|
||||
@Override
|
||||
public void render() {
|
||||
System.out.println(content.toString());
|
||||
}
|
||||
}
|
||||
|
@ -12,27 +12,27 @@ import com.iluwatar.flux.store.Store;
|
||||
*/
|
||||
public class MenuView implements View {
|
||||
|
||||
private MenuItem selected = MenuItem.HOME;
|
||||
|
||||
@Override
|
||||
public void storeChanged(Store store) {
|
||||
MenuStore menuStore = (MenuStore) store;
|
||||
selected = menuStore.getSelected();
|
||||
render();
|
||||
}
|
||||
private MenuItem selected = MenuItem.HOME;
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
for (MenuItem item: MenuItem.values()) {
|
||||
if (selected.equals(item)) {
|
||||
System.out.println(String.format("* %s", item.toString()));
|
||||
} else {
|
||||
System.out.println(item.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void itemClicked(MenuItem item) {
|
||||
Dispatcher.getInstance().menuItemSelected(item);
|
||||
}
|
||||
@Override
|
||||
public void storeChanged(Store store) {
|
||||
MenuStore menuStore = (MenuStore) store;
|
||||
selected = menuStore.getSelected();
|
||||
render();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
for (MenuItem item : MenuItem.values()) {
|
||||
if (selected.equals(item)) {
|
||||
System.out.println(String.format("* %s", item.toString()));
|
||||
} else {
|
||||
System.out.println(item.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void itemClicked(MenuItem item) {
|
||||
Dispatcher.getInstance().menuItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import com.iluwatar.flux.store.Store;
|
||||
*/
|
||||
public interface View {
|
||||
|
||||
public void storeChanged(Store store);
|
||||
public void storeChanged(Store store);
|
||||
|
||||
public void render();
|
||||
public void render();
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ import com.iluwatar.flux.app.App;
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -5,53 +5,52 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* AlchemistShop holds potions on its shelves.
|
||||
* It uses PotionFactory to provide the potions.
|
||||
* AlchemistShop holds potions on its shelves. It uses PotionFactory to provide the potions.
|
||||
*
|
||||
*/
|
||||
public class AlchemistShop {
|
||||
|
||||
private List<Potion> topShelf;
|
||||
private List<Potion> bottomShelf;
|
||||
private List<Potion> topShelf;
|
||||
private List<Potion> bottomShelf;
|
||||
|
||||
public AlchemistShop() {
|
||||
topShelf = new ArrayList<>();
|
||||
bottomShelf = new ArrayList<>();
|
||||
fillShelves();
|
||||
}
|
||||
public AlchemistShop() {
|
||||
topShelf = new ArrayList<>();
|
||||
bottomShelf = new ArrayList<>();
|
||||
fillShelves();
|
||||
}
|
||||
|
||||
private void fillShelves() {
|
||||
private void fillShelves() {
|
||||
|
||||
PotionFactory factory = new PotionFactory();
|
||||
PotionFactory factory = new PotionFactory();
|
||||
|
||||
topShelf.add(factory.createPotion(PotionType.INVISIBILITY));
|
||||
topShelf.add(factory.createPotion(PotionType.INVISIBILITY));
|
||||
topShelf.add(factory.createPotion(PotionType.STRENGTH));
|
||||
topShelf.add(factory.createPotion(PotionType.HEALING));
|
||||
topShelf.add(factory.createPotion(PotionType.INVISIBILITY));
|
||||
topShelf.add(factory.createPotion(PotionType.STRENGTH));
|
||||
topShelf.add(factory.createPotion(PotionType.HEALING));
|
||||
topShelf.add(factory.createPotion(PotionType.HEALING));
|
||||
topShelf.add(factory.createPotion(PotionType.INVISIBILITY));
|
||||
topShelf.add(factory.createPotion(PotionType.INVISIBILITY));
|
||||
topShelf.add(factory.createPotion(PotionType.STRENGTH));
|
||||
topShelf.add(factory.createPotion(PotionType.HEALING));
|
||||
topShelf.add(factory.createPotion(PotionType.INVISIBILITY));
|
||||
topShelf.add(factory.createPotion(PotionType.STRENGTH));
|
||||
topShelf.add(factory.createPotion(PotionType.HEALING));
|
||||
topShelf.add(factory.createPotion(PotionType.HEALING));
|
||||
|
||||
bottomShelf.add(factory.createPotion(PotionType.POISON));
|
||||
bottomShelf.add(factory.createPotion(PotionType.POISON));
|
||||
bottomShelf.add(factory.createPotion(PotionType.POISON));
|
||||
bottomShelf.add(factory.createPotion(PotionType.HOLY_WATER));
|
||||
bottomShelf.add(factory.createPotion(PotionType.HOLY_WATER));
|
||||
}
|
||||
bottomShelf.add(factory.createPotion(PotionType.POISON));
|
||||
bottomShelf.add(factory.createPotion(PotionType.POISON));
|
||||
bottomShelf.add(factory.createPotion(PotionType.POISON));
|
||||
bottomShelf.add(factory.createPotion(PotionType.HOLY_WATER));
|
||||
bottomShelf.add(factory.createPotion(PotionType.HOLY_WATER));
|
||||
}
|
||||
|
||||
public void enumerate() {
|
||||
public void enumerate() {
|
||||
|
||||
System.out.println("Enumerating top shelf potions\n");
|
||||
System.out.println("Enumerating top shelf potions\n");
|
||||
|
||||
for (Potion p : topShelf) {
|
||||
p.drink();
|
||||
}
|
||||
for (Potion p : topShelf) {
|
||||
p.drink();
|
||||
}
|
||||
|
||||
System.out.println("\nEnumerating bottom shelf potions\n");
|
||||
System.out.println("\nEnumerating bottom shelf potions\n");
|
||||
|
||||
for (Potion p : bottomShelf) {
|
||||
p.drink();
|
||||
}
|
||||
}
|
||||
for (Potion p : bottomShelf) {
|
||||
p.drink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,26 +2,27 @@ package com.iluwatar.flyweight;
|
||||
|
||||
/**
|
||||
*
|
||||
* Flyweight pattern is useful when the program needs a huge amount of objects.
|
||||
* It provides means to decrease resource usage by sharing object instances.
|
||||
* Flyweight pattern is useful when the program needs a huge amount of objects. It provides means to
|
||||
* decrease resource usage by sharing object instances.
|
||||
* <p>
|
||||
* In this example {@link AlchemistShop} has great amount of potions on its shelves.
|
||||
* To fill the shelves {@link AlchemistShop} uses {@link PotionFactory} (which represents
|
||||
* the Flyweight in this example). Internally {@link PotionFactory} holds a map
|
||||
* of the potions and lazily creates new ones when requested.
|
||||
* In this example {@link AlchemistShop} has great amount of potions on its shelves. To fill the
|
||||
* shelves {@link AlchemistShop} uses {@link PotionFactory} (which represents the Flyweight in this
|
||||
* example). Internally {@link PotionFactory} holds a map of the potions and lazily creates new ones
|
||||
* when requested.
|
||||
* <p>
|
||||
* To enable safe sharing, between clients and threads, Flyweight objects must
|
||||
* be immutable. Flyweight objects are by definition value objects.
|
||||
* To enable safe sharing, between clients and threads, Flyweight objects must be immutable.
|
||||
* Flyweight objects are by definition value objects.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
AlchemistShop alchemistShop = new AlchemistShop();
|
||||
alchemistShop.enumerate();
|
||||
}
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
AlchemistShop alchemistShop = new AlchemistShop();
|
||||
alchemistShop.enumerate();
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,8 @@ package com.iluwatar.flyweight;
|
||||
*/
|
||||
public class HealingPotion implements Potion {
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You feel healed. (Potion="
|
||||
+ System.identityHashCode(this) + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You feel healed. (Potion=" + System.identityHashCode(this) + ")");
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,8 @@ package com.iluwatar.flyweight;
|
||||
*/
|
||||
public class HolyWaterPotion implements Potion {
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You feel blessed. (Potion="
|
||||
+ System.identityHashCode(this) + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You feel blessed. (Potion=" + System.identityHashCode(this) + ")");
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,8 @@ package com.iluwatar.flyweight;
|
||||
*/
|
||||
public class InvisibilityPotion implements Potion {
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You become invisible. (Potion="
|
||||
+ System.identityHashCode(this) + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You become invisible. (Potion=" + System.identityHashCode(this) + ")");
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,8 @@ package com.iluwatar.flyweight;
|
||||
*/
|
||||
public class PoisonPotion implements Potion {
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("Urgh! This is poisonous. (Potion="
|
||||
+ System.identityHashCode(this) + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("Urgh! This is poisonous. (Potion=" + System.identityHashCode(this) + ")");
|
||||
}
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ package com.iluwatar.flyweight;
|
||||
*/
|
||||
public interface Potion {
|
||||
|
||||
void drink();
|
||||
void drink();
|
||||
}
|
||||
|
@ -5,48 +5,47 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* PotionFactory is the Flyweight in this example.
|
||||
* It minimizes memory use by sharing object instances.
|
||||
* It holds a map of potion instances and new potions
|
||||
* are created only when none of the type already exists.
|
||||
* PotionFactory is the Flyweight in this example. It minimizes memory use by sharing object
|
||||
* instances. It holds a map of potion instances and new potions are created only when none of the
|
||||
* type already exists.
|
||||
*
|
||||
*/
|
||||
public class PotionFactory {
|
||||
|
||||
private final Map<PotionType, Potion> potions;
|
||||
private final Map<PotionType, Potion> potions;
|
||||
|
||||
public PotionFactory() {
|
||||
potions = new EnumMap<>(PotionType.class);
|
||||
}
|
||||
public PotionFactory() {
|
||||
potions = new EnumMap<>(PotionType.class);
|
||||
}
|
||||
|
||||
Potion createPotion(PotionType type) {
|
||||
Potion potion = potions.get(type);
|
||||
if (potion == null) {
|
||||
switch (type) {
|
||||
case HEALING:
|
||||
potion = new HealingPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case HOLY_WATER:
|
||||
potion = new HolyWaterPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case INVISIBILITY:
|
||||
potion = new InvisibilityPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case POISON:
|
||||
potion = new PoisonPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case STRENGTH:
|
||||
potion = new StrengthPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return potion;
|
||||
}
|
||||
Potion createPotion(PotionType type) {
|
||||
Potion potion = potions.get(type);
|
||||
if (potion == null) {
|
||||
switch (type) {
|
||||
case HEALING:
|
||||
potion = new HealingPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case HOLY_WATER:
|
||||
potion = new HolyWaterPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case INVISIBILITY:
|
||||
potion = new InvisibilityPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case POISON:
|
||||
potion = new PoisonPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
case STRENGTH:
|
||||
potion = new StrengthPotion();
|
||||
potions.put(type, potion);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return potion;
|
||||
}
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ package com.iluwatar.flyweight;
|
||||
*/
|
||||
public enum PotionType {
|
||||
|
||||
HEALING, INVISIBILITY, STRENGTH, HOLY_WATER, POISON
|
||||
HEALING, INVISIBILITY, STRENGTH, HOLY_WATER, POISON
|
||||
}
|
||||
|
@ -7,9 +7,8 @@ package com.iluwatar.flyweight;
|
||||
*/
|
||||
public class StrengthPotion implements Potion {
|
||||
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You feel strong. (Potion="
|
||||
+ System.identityHashCode(this) + ")");
|
||||
}
|
||||
@Override
|
||||
public void drink() {
|
||||
System.out.println("You feel strong. (Potion=" + System.identityHashCode(this) + ")");
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import com.iluwatar.flyweight.App;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -8,122 +8,120 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
* {@link AsyncTask} and {@link AsynchronousService}.
|
||||
*
|
||||
* <p>
|
||||
* <i>PROBLEM</i>
|
||||
* <br/>
|
||||
* A concurrent system have a mixture of short duration, mid duration and long duration tasks.
|
||||
* Mid or long duration tasks should be performed asynchronously to meet quality of service
|
||||
* <i>PROBLEM</i> <br/>
|
||||
* A concurrent system have a mixture of short duration, mid duration and long duration tasks. Mid
|
||||
* or long duration tasks should be performed asynchronously to meet quality of service
|
||||
* requirements.
|
||||
*
|
||||
* <p><i>INTENT</i>
|
||||
* <br/>
|
||||
* The intent of this pattern is to separate the the synchronous and asynchronous processing
|
||||
* in the concurrent application by introducing two intercommunicating layers - one for sync
|
||||
* and one for async. This simplifies the programming without unduly affecting the performance.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <i>APPLICABILITY</i>
|
||||
* <br/>
|
||||
* <i>INTENT</i> <br/>
|
||||
* The intent of this pattern is to separate the the synchronous and asynchronous processing in the
|
||||
* concurrent application by introducing two intercommunicating layers - one for sync and one for
|
||||
* async. This simplifies the programming without unduly affecting the performance.
|
||||
*
|
||||
* <p>
|
||||
* <i>APPLICABILITY</i> <br/>
|
||||
* <ul>
|
||||
* <li>UNIX network subsystems - In operating systems network operations are carried out
|
||||
* asynchronously with help of hardware level interrupts.</li>
|
||||
* <li>CORBA - At the asynchronous layer one thread is associated with each socket that is
|
||||
* connected to the client. Thread blocks waiting for CORBA requests from the client. On receiving
|
||||
* request it is inserted in the queuing layer which is then picked up by synchronous layer which
|
||||
* processes the request and sends response back to the client.</li>
|
||||
* <li>Android AsyncTask framework - Framework provides a way to execute long running blocking calls,
|
||||
* such as downloading a file, in background threads so that the UI thread remains free to respond
|
||||
* to user inputs.</i>
|
||||
* </ul>
|
||||
*
|
||||
* <li>CORBA - At the asynchronous layer one thread is associated with each socket that is connected
|
||||
* to the client. Thread blocks waiting for CORBA requests from the client. On receiving request it
|
||||
* is inserted in the queuing layer which is then picked up by synchronous layer which processes the
|
||||
* request and sends response back to the client.</li>
|
||||
* <li>Android AsyncTask framework - Framework provides a way to execute long running blocking
|
||||
* calls, such as downloading a file, in background threads so that the UI thread remains free to
|
||||
* respond to user inputs.</i>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* <i>IMPLEMENTATION</i>
|
||||
* <br/>
|
||||
* The main method creates an asynchronous service which does not block the main thread while
|
||||
* the task is being performed. The main thread continues its work which is similar to Async Method
|
||||
* Invocation pattern. The difference between them is that there is a queuing layer between Asynchronous
|
||||
* layer and synchronous layer, which allows for different communication patterns between both layers.
|
||||
* Such as Priority Queue can be used as queuing layer to prioritize the way tasks are executed.
|
||||
* Our implementation is just one simple way of implementing this pattern, there are many variants possible
|
||||
* as described in its applications.
|
||||
* <i>IMPLEMENTATION</i> <br/>
|
||||
* The main method creates an asynchronous service which does not block the main thread while the
|
||||
* task is being performed. The main thread continues its work which is similar to Async Method
|
||||
* Invocation pattern. The difference between them is that there is a queuing layer between
|
||||
* Asynchronous layer and synchronous layer, which allows for different communication patterns
|
||||
* between both layers. Such as Priority Queue can be used as queuing layer to prioritize the way
|
||||
* tasks are executed. Our implementation is just one simple way of implementing this pattern, there
|
||||
* are many variants possible as described in its applications.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>());
|
||||
/*
|
||||
* A new task to calculate sum is received but as this is main thread, it should not block.
|
||||
* So it passes it to the asynchronous task layer to compute and proceeds with handling other
|
||||
* incoming requests. This is particularly useful when main thread is waiting on Socket to receive
|
||||
* new incoming requests and does not wait for particular request to be completed before responding
|
||||
* to new request.
|
||||
*/
|
||||
service.execute(new ArithmeticSumTask(1000));
|
||||
|
||||
/* New task received, lets pass that to async layer for computation. So both requests will be
|
||||
* executed in parallel.
|
||||
*/
|
||||
service.execute(new ArithmeticSumTask(500));
|
||||
service.execute(new ArithmeticSumTask(2000));
|
||||
service.execute(new ArithmeticSumTask(1));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* ArithmeticSumTask
|
||||
*
|
||||
*/
|
||||
static class ArithmeticSumTask implements AsyncTask<Long> {
|
||||
private long n;
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>());
|
||||
/*
|
||||
* A new task to calculate sum is received but as this is main thread, it should not block. So
|
||||
* it passes it to the asynchronous task layer to compute and proceeds with handling other
|
||||
* incoming requests. This is particularly useful when main thread is waiting on Socket to
|
||||
* receive new incoming requests and does not wait for particular request to be completed before
|
||||
* responding to new request.
|
||||
*/
|
||||
service.execute(new ArithmeticSumTask(1000));
|
||||
|
||||
public ArithmeticSumTask(long n) {
|
||||
this.n = n;
|
||||
}
|
||||
/*
|
||||
* New task received, lets pass that to async layer for computation. So both requests will be
|
||||
* executed in parallel.
|
||||
*/
|
||||
service.execute(new ArithmeticSumTask(500));
|
||||
service.execute(new ArithmeticSumTask(2000));
|
||||
service.execute(new ArithmeticSumTask(1));
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the long running task that is performed in background. In our example
|
||||
* the long running task is calculating arithmetic sum with artificial delay.
|
||||
*/
|
||||
@Override
|
||||
public Long call() throws Exception {
|
||||
return ap(n);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* ArithmeticSumTask
|
||||
*
|
||||
*/
|
||||
static class ArithmeticSumTask implements AsyncTask<Long> {
|
||||
private long n;
|
||||
|
||||
/*
|
||||
* This will be called in context of the main thread where some validations can be
|
||||
* done regarding the inputs. Such as it must be greater than 0. It's a small
|
||||
* computation which can be performed in main thread. If we did validated the input
|
||||
* in background thread then we pay the cost of context switching
|
||||
* which is much more than validating it in main thread.
|
||||
*/
|
||||
@Override
|
||||
public void onPreCall() {
|
||||
if (n < 0) {
|
||||
throw new IllegalArgumentException("n is less than 0");
|
||||
}
|
||||
}
|
||||
public ArithmeticSumTask(long n) {
|
||||
this.n = n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostCall(Long result) {
|
||||
// Handle the result of computation
|
||||
System.out.println(result);
|
||||
}
|
||||
/*
|
||||
* This is the long running task that is performed in background. In our example the long
|
||||
* running task is calculating arithmetic sum with artificial delay.
|
||||
*/
|
||||
@Override
|
||||
public Long call() throws Exception {
|
||||
return ap(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
throw new IllegalStateException("Should not occur");
|
||||
}
|
||||
}
|
||||
|
||||
private static long ap(long i) {
|
||||
try {
|
||||
Thread.sleep(i);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
return (i) * (i + 1) / 2;
|
||||
}
|
||||
/*
|
||||
* This will be called in context of the main thread where some validations can be done
|
||||
* regarding the inputs. Such as it must be greater than 0. It's a small computation which can
|
||||
* be performed in main thread. If we did validated the input in background thread then we pay
|
||||
* the cost of context switching which is much more than validating it in main thread.
|
||||
*/
|
||||
@Override
|
||||
public void onPreCall() {
|
||||
if (n < 0) {
|
||||
throw new IllegalArgumentException("n is less than 0");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostCall(Long result) {
|
||||
// Handle the result of computation
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
throw new IllegalStateException("Should not occur");
|
||||
}
|
||||
}
|
||||
|
||||
private static long ap(long i) {
|
||||
try {
|
||||
Thread.sleep(i);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
return (i) * (i + 1) / 2;
|
||||
}
|
||||
}
|
||||
|
@ -3,42 +3,42 @@ package com.iluwatar.halfsynchalfasync;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Represents some computation that is performed asynchronously and its result.
|
||||
* The computation is typically done is background threads and the result is posted
|
||||
* back in form of callback. The callback does not implement {@code isComplete}, {@code cancel}
|
||||
* as it is out of scope of this pattern.
|
||||
* Represents some computation that is performed asynchronously and its result. The computation is
|
||||
* typically done is background threads and the result is posted back in form of callback. The
|
||||
* callback does not implement {@code isComplete}, {@code cancel} as it is out of scope of this
|
||||
* pattern.
|
||||
*
|
||||
* @param <O> type of result
|
||||
*/
|
||||
public interface AsyncTask<O> extends Callable<O> {
|
||||
/**
|
||||
* Is called in context of caller thread before call to {@link #call()}. Large
|
||||
* tasks should not be performed in this method as it will block the caller thread.
|
||||
* Small tasks such as validations can be performed here so that the performance penalty
|
||||
* of context switching is not incurred in case of invalid requests.
|
||||
*/
|
||||
void onPreCall();
|
||||
|
||||
/**
|
||||
* A callback called after the result is successfully computed by {@link #call()}. In our
|
||||
* implementation this method is called in context of background thread but in some variants,
|
||||
* such as Android where only UI thread can change the state of UI widgets, this method is called
|
||||
* in context of UI thread.
|
||||
*/
|
||||
void onPostCall(O result);
|
||||
|
||||
/**
|
||||
* A callback called if computing the task resulted in some exception. This method
|
||||
* is called when either of {@link #call()} or {@link #onPreCall()} throw any exception.
|
||||
*
|
||||
* @param throwable error cause
|
||||
*/
|
||||
void onError(Throwable throwable);
|
||||
|
||||
/**
|
||||
* This is where the computation of task should reside. This method is called in context
|
||||
* of background thread.
|
||||
*/
|
||||
@Override
|
||||
O call() throws Exception;
|
||||
/**
|
||||
* Is called in context of caller thread before call to {@link #call()}. Large tasks should not be
|
||||
* performed in this method as it will block the caller thread. Small tasks such as validations
|
||||
* can be performed here so that the performance penalty of context switching is not incurred in
|
||||
* case of invalid requests.
|
||||
*/
|
||||
void onPreCall();
|
||||
|
||||
/**
|
||||
* A callback called after the result is successfully computed by {@link #call()}. In our
|
||||
* implementation this method is called in context of background thread but in some variants, such
|
||||
* as Android where only UI thread can change the state of UI widgets, this method is called in
|
||||
* context of UI thread.
|
||||
*/
|
||||
void onPostCall(O result);
|
||||
|
||||
/**
|
||||
* A callback called if computing the task resulted in some exception. This method is called when
|
||||
* either of {@link #call()} or {@link #onPreCall()} throw any exception.
|
||||
*
|
||||
* @param throwable error cause
|
||||
*/
|
||||
void onError(Throwable throwable);
|
||||
|
||||
/**
|
||||
* This is where the computation of task should reside. This method is called in context of
|
||||
* background thread.
|
||||
*/
|
||||
@Override
|
||||
O call() throws Exception;
|
||||
}
|
||||
|
@ -9,67 +9,67 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* This is the asynchronous layer which does not block when a new request arrives. It just passes
|
||||
* the request to the synchronous layer which consists of a queue i.e. a {@link BlockingQueue} and
|
||||
* a pool of threads i.e. {@link ThreadPoolExecutor}. Out of this pool of worker threads one of the
|
||||
* thread picks up the task and executes it synchronously in background and the result is posted back
|
||||
* to the caller via callback.
|
||||
* the request to the synchronous layer which consists of a queue i.e. a {@link BlockingQueue} and a
|
||||
* pool of threads i.e. {@link ThreadPoolExecutor}. Out of this pool of worker threads one of the
|
||||
* thread picks up the task and executes it synchronously in background and the result is posted
|
||||
* back to the caller via callback.
|
||||
*/
|
||||
public class AsynchronousService {
|
||||
|
||||
/*
|
||||
* This represents the queuing layer as well as synchronous layer of the pattern. The thread
|
||||
* pool contains worker threads which execute the tasks in blocking/synchronous manner. Long
|
||||
* running tasks should be performed in the background which does not affect the performance of
|
||||
* main thread.
|
||||
*/
|
||||
private ExecutorService service;
|
||||
|
||||
/**
|
||||
* Creates an asynchronous service using {@code workQueue} as communication channel between
|
||||
* asynchronous layer and synchronous layer. Different types of queues such as Priority queue,
|
||||
* can be used to control the pattern of communication between the layers.
|
||||
*/
|
||||
public AsynchronousService(BlockingQueue<Runnable> workQueue) {
|
||||
service = new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS, workQueue);
|
||||
}
|
||||
|
||||
/*
|
||||
* This represents the queuing layer as well as synchronous layer of the pattern. The thread pool
|
||||
* contains worker threads which execute the tasks in blocking/synchronous manner. Long running
|
||||
* tasks should be performed in the background which does not affect the performance of main
|
||||
* thread.
|
||||
*/
|
||||
private ExecutorService service;
|
||||
|
||||
/**
|
||||
* A non-blocking method which performs the task provided in background and returns immediately.
|
||||
* <p>
|
||||
* On successful completion of task the result is posted back using callback method
|
||||
* {@link AsyncTask#onPostCall(Object)}, if task execution is unable to complete normally
|
||||
* due to some exception then the reason for error is posted back using callback method
|
||||
* {@link AsyncTask#onError(Throwable)}.
|
||||
* <p>
|
||||
* NOTE: The results are posted back in the context of background thread in this implementation.
|
||||
*/
|
||||
public <T> void execute(final AsyncTask<T> task) {
|
||||
try {
|
||||
// some small tasks such as validation can be performed here.
|
||||
task.onPreCall();
|
||||
} catch (Exception e) {
|
||||
task.onError(e);
|
||||
}
|
||||
/**
|
||||
* Creates an asynchronous service using {@code workQueue} as communication channel between
|
||||
* asynchronous layer and synchronous layer. Different types of queues such as Priority queue, can
|
||||
* be used to control the pattern of communication between the layers.
|
||||
*/
|
||||
public AsynchronousService(BlockingQueue<Runnable> workQueue) {
|
||||
service = new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS, workQueue);
|
||||
}
|
||||
|
||||
service.submit(new FutureTask<T>(task) {
|
||||
@Override
|
||||
protected void done() {
|
||||
super.done();
|
||||
try {
|
||||
/* called in context of background thread. There is other variant possible
|
||||
* where result is posted back and sits in the queue of caller thread which
|
||||
* then picks it up for processing. An example of such a system is Android OS,
|
||||
* where the UI elements can only be updated using UI thread. So result must be
|
||||
* posted back in UI thread.
|
||||
*/
|
||||
task.onPostCall(get());
|
||||
} catch (InterruptedException e) {
|
||||
// should not occur
|
||||
} catch (ExecutionException e) {
|
||||
task.onError(e.getCause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A non-blocking method which performs the task provided in background and returns immediately.
|
||||
* <p>
|
||||
* On successful completion of task the result is posted back using callback method
|
||||
* {@link AsyncTask#onPostCall(Object)}, if task execution is unable to complete normally due to
|
||||
* some exception then the reason for error is posted back using callback method
|
||||
* {@link AsyncTask#onError(Throwable)}.
|
||||
* <p>
|
||||
* NOTE: The results are posted back in the context of background thread in this implementation.
|
||||
*/
|
||||
public <T> void execute(final AsyncTask<T> task) {
|
||||
try {
|
||||
// some small tasks such as validation can be performed here.
|
||||
task.onPreCall();
|
||||
} catch (Exception e) {
|
||||
task.onError(e);
|
||||
}
|
||||
|
||||
service.submit(new FutureTask<T>(task) {
|
||||
@Override
|
||||
protected void done() {
|
||||
super.done();
|
||||
try {
|
||||
/*
|
||||
* called in context of background thread. There is other variant possible where result is
|
||||
* posted back and sits in the queue of caller thread which then picks it up for
|
||||
* processing. An example of such a system is Android OS, where the UI elements can only
|
||||
* be updated using UI thread. So result must be posted back in UI thread.
|
||||
*/
|
||||
task.onPostCall(get());
|
||||
} catch (InterruptedException e) {
|
||||
// should not occur
|
||||
} catch (ExecutionException e) {
|
||||
task.onError(e.getCause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ import org.junit.Test;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() throws InterruptedException, ExecutionException {
|
||||
App.main(null);
|
||||
}
|
||||
@Test
|
||||
public void test() throws InterruptedException, ExecutionException {
|
||||
App.main(null);
|
||||
}
|
||||
}
|
||||
|
@ -1,46 +1,44 @@
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
/**
|
||||
* Base class for order processing filters.
|
||||
* Handles chain management.
|
||||
* Base class for order processing filters. Handles chain management.
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractFilter implements Filter {
|
||||
|
||||
private Filter next;
|
||||
|
||||
public AbstractFilter() {
|
||||
}
|
||||
private Filter next;
|
||||
|
||||
public AbstractFilter(Filter next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNext(Filter filter) {
|
||||
this.next = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getNext() {
|
||||
return next;
|
||||
}
|
||||
public AbstractFilter() {}
|
||||
|
||||
@Override
|
||||
public Filter getLast() {
|
||||
Filter last = this;
|
||||
while (last.getNext() != null) {
|
||||
last = last.getNext();
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
if (getNext() != null) {
|
||||
return getNext().execute(order);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
public AbstractFilter(Filter next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNext(Filter filter) {
|
||||
this.next = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getLast() {
|
||||
Filter last = this;
|
||||
while (last.getNext() != null) {
|
||||
last = last.getNext();
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
if (getNext() != null) {
|
||||
return getNext().execute(order);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
/**
|
||||
* Concrete implementation of filter
|
||||
* This filter is responsible for checking/filtering the input in the address field.
|
||||
* Concrete implementation of filter This filter is responsible for checking/filtering the input in
|
||||
* the address field.
|
||||
*
|
||||
* @author joshzambales
|
||||
*
|
||||
*/
|
||||
public class AddressFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getAddress() == null || order.getAddress().isEmpty()) {
|
||||
return result + "Invalid address! ";
|
||||
} else
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getAddress() == null || order.getAddress().isEmpty()) {
|
||||
return result + "Invalid address! ";
|
||||
} else
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -2,50 +2,46 @@ package com.iluwatar.intercepting.filter;
|
||||
|
||||
/**
|
||||
*
|
||||
* When a request enters a Web application, it often must pass several entrance
|
||||
* tests prior to the main processing stage. For example,
|
||||
* - Has the client been authenticated?
|
||||
* - Does the client have a valid session?
|
||||
* - Is the client's IP address from a trusted network?
|
||||
* - Does the request path violate any constraints?
|
||||
* - What encoding does the client use to send the data?
|
||||
* - Do we support the browser type of the client?
|
||||
* Some of these checks are tests, resulting in a yes or no answer that determines
|
||||
* whether processing will continue. Other checks manipulate the incoming data
|
||||
* When a request enters a Web application, it often must pass several entrance tests prior to the
|
||||
* main processing stage. For example, - Has the client been authenticated? - Does the client have a
|
||||
* valid session? - Is the client's IP address from a trusted network? - Does the request path
|
||||
* violate any constraints? - What encoding does the client use to send the data? - Do we support
|
||||
* the browser type of the client? Some of these checks are tests, resulting in a yes or no answer
|
||||
* that determines whether processing will continue. Other checks manipulate the incoming data
|
||||
* stream into a form suitable for processing.
|
||||
* <p>
|
||||
* The classic solution consists of a series of conditional checks, with any failed
|
||||
* check aborting the request. Nested if/else statements are a standard strategy,
|
||||
* but this solution leads to code fragility and a copy-and-paste style of programming,
|
||||
* because the flow of the filtering and the action of the filters is compiled into
|
||||
* the application.
|
||||
* The classic solution consists of a series of conditional checks, with any failed check aborting
|
||||
* the request. Nested if/else statements are a standard strategy, but this solution leads to code
|
||||
* fragility and a copy-and-paste style of programming, because the flow of the filtering and the
|
||||
* action of the filters is compiled into the application.
|
||||
* <p>
|
||||
* The key to solving this problem in a flexible and unobtrusive manner is to have a
|
||||
* simple mechanism for adding and removing processing components, in which each
|
||||
* component completes a specific filtering action. This is the Intercepting Filter
|
||||
* pattern in action.
|
||||
* The key to solving this problem in a flexible and unobtrusive manner is to have a simple
|
||||
* mechanism for adding and removing processing components, in which each component completes a
|
||||
* specific filtering action. This is the Intercepting Filter pattern in action.
|
||||
* <p>
|
||||
* In this example we check whether the order request is valid through pre-processing
|
||||
* done via {@link Filter}. Each field has its own corresponding {@link Filter}
|
||||
* In this example we check whether the order request is valid through pre-processing done via
|
||||
* {@link Filter}. Each field has its own corresponding {@link Filter}
|
||||
* <p>
|
||||
*
|
||||
* @author joshzambales
|
||||
*
|
||||
*/
|
||||
public class App{
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
FilterManager filterManager = new FilterManager(new Target());
|
||||
filterManager.addFilter(new NameFilter());
|
||||
filterManager.addFilter(new ContactFilter());
|
||||
filterManager.addFilter(new AddressFilter());
|
||||
filterManager.addFilter(new DepositFilter());
|
||||
filterManager.addFilter(new OrderFilter());
|
||||
public class App {
|
||||
|
||||
Client client = new Client();
|
||||
client.setFilterManager(filterManager);
|
||||
}
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
FilterManager filterManager = new FilterManager(new Target());
|
||||
filterManager.addFilter(new NameFilter());
|
||||
filterManager.addFilter(new ContactFilter());
|
||||
filterManager.addFilter(new AddressFilter());
|
||||
filterManager.addFilter(new DepositFilter());
|
||||
filterManager.addFilter(new OrderFilter());
|
||||
|
||||
Client client = new Client();
|
||||
client.setFilterManager(filterManager);
|
||||
}
|
||||
}
|
||||
|
@ -15,93 +15,95 @@ import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* The Client class is responsible for handling the input and running them through filters inside the {@link FilterManager}.
|
||||
* The Client class is responsible for handling the input and running them through filters inside
|
||||
* the {@link FilterManager}.
|
||||
*
|
||||
* This is where {@link Filter}s come to play as the client pre-processes the request before being displayed in the {@link Target}.
|
||||
* This is where {@link Filter}s come to play as the client pre-processes the request before being
|
||||
* displayed in the {@link Target}.
|
||||
*
|
||||
* @author joshzambales
|
||||
*
|
||||
*/
|
||||
public class Client extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private FilterManager filterManager;
|
||||
private JLabel jl;
|
||||
private JTextField[] jtFields;
|
||||
private JTextArea[] jtAreas;
|
||||
private JButton clearButton, processButton;
|
||||
private FilterManager filterManager;
|
||||
private JLabel jl;
|
||||
private JTextField[] jtFields;
|
||||
private JTextArea[] jtAreas;
|
||||
private JButton clearButton, processButton;
|
||||
|
||||
public Client() {
|
||||
super("Client System");
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setSize(300, 300);
|
||||
jl = new JLabel("RUNNING...");
|
||||
jtFields = new JTextField[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
jtFields[i] = new JTextField();
|
||||
}
|
||||
jtAreas = new JTextArea[2];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
jtAreas[i] = new JTextArea();
|
||||
}
|
||||
clearButton = new JButton("Clear");
|
||||
processButton = new JButton("Process");
|
||||
public Client() {
|
||||
super("Client System");
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setSize(300, 300);
|
||||
jl = new JLabel("RUNNING...");
|
||||
jtFields = new JTextField[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
jtFields[i] = new JTextField();
|
||||
}
|
||||
jtAreas = new JTextArea[2];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
jtAreas[i] = new JTextArea();
|
||||
}
|
||||
clearButton = new JButton("Clear");
|
||||
processButton = new JButton("Process");
|
||||
|
||||
setup();
|
||||
}
|
||||
setup();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
setLayout(new BorderLayout());
|
||||
JPanel panel = new JPanel();
|
||||
add(jl, BorderLayout.SOUTH);
|
||||
add(panel, BorderLayout.CENTER);
|
||||
panel.setLayout(new GridLayout(6, 2));
|
||||
panel.add(new JLabel("Name"));
|
||||
panel.add(jtFields[0]);
|
||||
panel.add(new JLabel("Contact Number"));
|
||||
panel.add(jtFields[1]);
|
||||
panel.add(new JLabel("Address"));
|
||||
panel.add(jtAreas[0]);
|
||||
panel.add(new JLabel("Deposit Number"));
|
||||
panel.add(jtFields[2]);
|
||||
panel.add(new JLabel("Order"));
|
||||
panel.add(jtAreas[1]);
|
||||
panel.add(clearButton);
|
||||
panel.add(processButton);
|
||||
private void setup() {
|
||||
setLayout(new BorderLayout());
|
||||
JPanel panel = new JPanel();
|
||||
add(jl, BorderLayout.SOUTH);
|
||||
add(panel, BorderLayout.CENTER);
|
||||
panel.setLayout(new GridLayout(6, 2));
|
||||
panel.add(new JLabel("Name"));
|
||||
panel.add(jtFields[0]);
|
||||
panel.add(new JLabel("Contact Number"));
|
||||
panel.add(jtFields[1]);
|
||||
panel.add(new JLabel("Address"));
|
||||
panel.add(jtAreas[0]);
|
||||
panel.add(new JLabel("Deposit Number"));
|
||||
panel.add(jtFields[2]);
|
||||
panel.add(new JLabel("Order"));
|
||||
panel.add(jtAreas[1]);
|
||||
panel.add(clearButton);
|
||||
panel.add(processButton);
|
||||
|
||||
clearButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
for (JTextArea i : jtAreas) {
|
||||
i.setText("");
|
||||
}
|
||||
for (JTextField i : jtFields) {
|
||||
i.setText("");
|
||||
}
|
||||
}
|
||||
});
|
||||
clearButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
for (JTextArea i : jtAreas) {
|
||||
i.setText("");
|
||||
}
|
||||
for (JTextField i : jtFields) {
|
||||
i.setText("");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
processButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Order order = new Order(jtFields[0].getText(), jtFields[1]
|
||||
.getText(), jtAreas[0].getText(),
|
||||
jtFields[2].getText(), jtAreas[1].getText());
|
||||
jl.setText(sendRequest(order));
|
||||
}
|
||||
});
|
||||
processButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Order order =
|
||||
new Order(jtFields[0].getText(), jtFields[1].getText(), jtAreas[0].getText(),
|
||||
jtFields[2].getText(), jtAreas[1].getText());
|
||||
jl.setText(sendRequest(order));
|
||||
}
|
||||
});
|
||||
|
||||
JRootPane rootPane = SwingUtilities.getRootPane(processButton);
|
||||
rootPane.setDefaultButton(processButton);
|
||||
setVisible(true);
|
||||
}
|
||||
JRootPane rootPane = SwingUtilities.getRootPane(processButton);
|
||||
rootPane.setDefaultButton(processButton);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
public void setFilterManager(FilterManager filterManager) {
|
||||
this.filterManager = filterManager;
|
||||
}
|
||||
public void setFilterManager(FilterManager filterManager) {
|
||||
this.filterManager = filterManager;
|
||||
}
|
||||
|
||||
public String sendRequest(Order order) {
|
||||
return filterManager.filterRequest(order);
|
||||
}
|
||||
public String sendRequest(Order order) {
|
||||
return filterManager.filterRequest(order);
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
/**
|
||||
* Concrete implementation of filter
|
||||
* This filter checks for the contact field in which it checks if the input consist of numbers
|
||||
* and it also checks if the input follows the length constraint (11 digits)
|
||||
* Concrete implementation of filter This filter checks for the contact field in which it checks if
|
||||
* the input consist of numbers and it also checks if the input follows the length constraint (11
|
||||
* digits)
|
||||
*
|
||||
* @author joshzambales
|
||||
*
|
||||
*/
|
||||
public class ContactFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getContactNumber() == null
|
||||
|| order.getContactNumber().isEmpty()
|
||||
|| order.getContactNumber().matches(".*[^\\d]+.*")
|
||||
|| order.getContactNumber().length() != 11) {
|
||||
return result + "Invalid contact number! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getContactNumber() == null || order.getContactNumber().isEmpty()
|
||||
|| order.getContactNumber().matches(".*[^\\d]+.*")
|
||||
|| order.getContactNumber().length() != 11) {
|
||||
return result + "Invalid contact number! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
/**
|
||||
* Concrete implementation of filter
|
||||
* This checks for the deposit code
|
||||
* Concrete implementation of filter This checks for the deposit code
|
||||
*
|
||||
* @author joshzambales
|
||||
*
|
||||
*/
|
||||
public class DepositFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getDepositNumber() == null || order.getDepositNumber().isEmpty()) {
|
||||
return result + "Invalid deposit number! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getDepositNumber() == null || order.getDepositNumber().isEmpty()) {
|
||||
return result + "Invalid deposit number! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,40 @@
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
/**
|
||||
* Filters perform certain tasks prior or after execution of
|
||||
* request by request handler. In this case, before the request is handled by
|
||||
* the target, the request undergoes through each Filter
|
||||
* Filters perform certain tasks prior or after execution of request by request handler. In this
|
||||
* case, before the request is handled by the target, the request undergoes through each Filter
|
||||
*
|
||||
* @author joshzambales
|
||||
*
|
||||
*/
|
||||
public interface Filter {
|
||||
|
||||
/**
|
||||
* Execute order processing filter.
|
||||
* @param order
|
||||
* @return empty string on success, otherwise error message.
|
||||
*/
|
||||
String execute(Order order);
|
||||
|
||||
/**
|
||||
* Set next filter in chain after this.
|
||||
* @param filter
|
||||
*/
|
||||
void setNext(Filter filter);
|
||||
|
||||
/**
|
||||
* Get next filter in chain after this.
|
||||
* @return
|
||||
*/
|
||||
Filter getNext();
|
||||
|
||||
/**
|
||||
* Get last filter in the chain.
|
||||
* @return
|
||||
*/
|
||||
Filter getLast();
|
||||
|
||||
/**
|
||||
* Execute order processing filter.
|
||||
*
|
||||
* @param order
|
||||
* @return empty string on success, otherwise error message.
|
||||
*/
|
||||
String execute(Order order);
|
||||
|
||||
/**
|
||||
* Set next filter in chain after this.
|
||||
*
|
||||
* @param filter
|
||||
*/
|
||||
void setNext(Filter filter);
|
||||
|
||||
/**
|
||||
* Get next filter in chain after this.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Filter getNext();
|
||||
|
||||
/**
|
||||
* Get last filter in the chain.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Filter getLast();
|
||||
}
|
||||
|
@ -1,34 +1,34 @@
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
|
||||
/**
|
||||
* Filter Chain carries multiple filters and help to execute them in defined order on target.
|
||||
*
|
||||
* @author joshzambales
|
||||
*/
|
||||
public class FilterChain {
|
||||
|
||||
private Filter chain;
|
||||
|
||||
private final Target target;
|
||||
|
||||
public FilterChain(Target target) {
|
||||
this.target = target;
|
||||
}
|
||||
private Filter chain;
|
||||
|
||||
public void addFilter(Filter filter) {
|
||||
if (chain == null) {
|
||||
chain = filter;
|
||||
} else {
|
||||
chain.getLast().setNext(filter);
|
||||
}
|
||||
}
|
||||
private final Target target;
|
||||
|
||||
public String execute(Order order) {
|
||||
if (chain != null) {
|
||||
return chain.execute(order);
|
||||
} else {
|
||||
return "RUNNING...";
|
||||
}
|
||||
}
|
||||
public FilterChain(Target target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public void addFilter(Filter filter) {
|
||||
if (chain == null) {
|
||||
chain = filter;
|
||||
} else {
|
||||
chain.getLast().setNext(filter);
|
||||
}
|
||||
}
|
||||
|
||||
public String execute(Order order) {
|
||||
if (chain != null) {
|
||||
return chain.execute(order);
|
||||
} else {
|
||||
return "RUNNING...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,18 +7,18 @@ package com.iluwatar.intercepting.filter;
|
||||
*
|
||||
*/
|
||||
public class FilterManager {
|
||||
|
||||
private FilterChain filterChain;
|
||||
|
||||
public FilterManager(Target target) {
|
||||
filterChain = new FilterChain(target);
|
||||
}
|
||||
private FilterChain filterChain;
|
||||
|
||||
public void addFilter(Filter filter) {
|
||||
filterChain.addFilter(filter);
|
||||
}
|
||||
public FilterManager(Target target) {
|
||||
filterChain = new FilterChain(target);
|
||||
}
|
||||
|
||||
public String filterRequest(Order order) {
|
||||
return filterChain.execute(order);
|
||||
}
|
||||
public void addFilter(Filter filter) {
|
||||
filterChain.addFilter(filter);
|
||||
}
|
||||
|
||||
public String filterRequest(Order order) {
|
||||
return filterChain.execute(order);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,22 @@
|
||||
package com.iluwatar.intercepting.filter;
|
||||
|
||||
/**
|
||||
* Concrete implementation of filter. This filter checks if the input in the Name
|
||||
* field is valid. (alphanumeric)
|
||||
* Concrete implementation of filter. This filter checks if the input in the Name field is valid.
|
||||
* (alphanumeric)
|
||||
*
|
||||
* @author joshzambales
|
||||
*
|
||||
*/
|
||||
public class NameFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getName() == null || order.getName().isEmpty() || order.getName().matches(".*[^\\w|\\s]+.*")) {
|
||||
return result + "Invalid order! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getName() == null || order.getName().isEmpty()
|
||||
|| order.getName().matches(".*[^\\w|\\s]+.*")) {
|
||||
return result + "Invalid order! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,60 +6,59 @@ package com.iluwatar.intercepting.filter;
|
||||
*/
|
||||
public class Order {
|
||||
|
||||
private String name;
|
||||
private String contactNumber;
|
||||
private String address;
|
||||
private String depositNumber;
|
||||
private String order;
|
||||
|
||||
public Order() {
|
||||
}
|
||||
private String name;
|
||||
private String contactNumber;
|
||||
private String address;
|
||||
private String depositNumber;
|
||||
private String order;
|
||||
|
||||
public Order(String name, String contactNumber, String address, String depositNumber, String order) {
|
||||
this.name = name;
|
||||
this.contactNumber = contactNumber;
|
||||
this.address = address;
|
||||
this.depositNumber = depositNumber;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public Order() {}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public Order(String name, String contactNumber, String address, String depositNumber, String order) {
|
||||
this.name = name;
|
||||
this.contactNumber = contactNumber;
|
||||
this.address = address;
|
||||
this.depositNumber = depositNumber;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public String getContactNumber() {
|
||||
return contactNumber;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setContactNumber(String contactNumber) {
|
||||
this.contactNumber = contactNumber;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
public String getContactNumber() {
|
||||
return contactNumber;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
public void setContactNumber(String contactNumber) {
|
||||
this.contactNumber = contactNumber;
|
||||
}
|
||||
|
||||
public String getDepositNumber() {
|
||||
return depositNumber;
|
||||
}
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setDepositNumber(String depositNumber) {
|
||||
this.depositNumber = depositNumber;
|
||||
}
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getOrder() {
|
||||
return order;
|
||||
}
|
||||
public String getDepositNumber() {
|
||||
return depositNumber;
|
||||
}
|
||||
|
||||
public void setOrder(String order) {
|
||||
this.order = order;
|
||||
}
|
||||
public void setDepositNumber(String depositNumber) {
|
||||
this.depositNumber = depositNumber;
|
||||
}
|
||||
|
||||
public String getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(String order) {
|
||||
this.order = order;
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ package com.iluwatar.intercepting.filter;
|
||||
*
|
||||
*/
|
||||
public class OrderFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getOrder() == null || order.getOrder().isEmpty()) {
|
||||
return result + "Invalid order! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(Order order) {
|
||||
String result = super.execute(order);
|
||||
if (order.getOrder() == null || order.getOrder().isEmpty()) {
|
||||
return result + "Invalid order! ";
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,57 +22,57 @@ import javax.swing.table.DefaultTableModel;
|
||||
*/
|
||||
public class Target extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JTable jt;
|
||||
private JScrollPane jsp;
|
||||
private DefaultTableModel dtm;
|
||||
private JButton del;
|
||||
private JTable jt;
|
||||
private JScrollPane jsp;
|
||||
private DefaultTableModel dtm;
|
||||
private JButton del;
|
||||
|
||||
public Target() {
|
||||
super("Order System");
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setSize(640, 480);
|
||||
dtm = new DefaultTableModel(new Object[] { "Name", "Contact Number",
|
||||
"Address", "Deposit Number", "Order" }, 0);
|
||||
jt = new JTable(dtm);
|
||||
del = new JButton("Delete");
|
||||
setup();
|
||||
}
|
||||
public Target() {
|
||||
super("Order System");
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setSize(640, 480);
|
||||
dtm =
|
||||
new DefaultTableModel(new Object[] {"Name", "Contact Number", "Address", "Deposit Number",
|
||||
"Order"}, 0);
|
||||
jt = new JTable(dtm);
|
||||
del = new JButton("Delete");
|
||||
setup();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
setLayout(new BorderLayout());
|
||||
JPanel bot = new JPanel();
|
||||
add(jt.getTableHeader(), BorderLayout.NORTH);
|
||||
bot.setLayout(new BorderLayout());
|
||||
bot.add(del, BorderLayout.EAST);
|
||||
add(bot, BorderLayout.SOUTH);
|
||||
jsp = new JScrollPane(jt);
|
||||
jsp.setPreferredSize(new Dimension(500, 250));
|
||||
add(jsp, BorderLayout.CENTER);
|
||||
private void setup() {
|
||||
setLayout(new BorderLayout());
|
||||
JPanel bot = new JPanel();
|
||||
add(jt.getTableHeader(), BorderLayout.NORTH);
|
||||
bot.setLayout(new BorderLayout());
|
||||
bot.add(del, BorderLayout.EAST);
|
||||
add(bot, BorderLayout.SOUTH);
|
||||
jsp = new JScrollPane(jt);
|
||||
jsp.setPreferredSize(new Dimension(500, 250));
|
||||
add(jsp, BorderLayout.CENTER);
|
||||
|
||||
del.addActionListener(new DListener());
|
||||
del.addActionListener(new DListener());
|
||||
|
||||
JRootPane rootPane = SwingUtilities.getRootPane(del);
|
||||
rootPane.setDefaultButton(del);
|
||||
setVisible(true);
|
||||
}
|
||||
JRootPane rootPane = SwingUtilities.getRootPane(del);
|
||||
rootPane.setDefaultButton(del);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
public void execute(String[] request) {
|
||||
dtm.addRow(new Object[] { request[0], request[1], request[2],
|
||||
request[3], request[4] });
|
||||
}
|
||||
public void execute(String[] request) {
|
||||
dtm.addRow(new Object[] {request[0], request[1], request[2], request[3], request[4]});
|
||||
}
|
||||
|
||||
class DListener implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int temp = jt.getSelectedRow();
|
||||
if (temp == -1)
|
||||
return;
|
||||
int temp2 = jt.getSelectedRowCount();
|
||||
for (int i = 0; i < temp2; i++) {
|
||||
dtm.removeRow(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
class DListener implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int temp = jt.getSelectedRow();
|
||||
if (temp == -1)
|
||||
return;
|
||||
int temp2 = jt.getSelectedRowCount();
|
||||
for (int i = 0; i < temp2; i++) {
|
||||
dtm.removeRow(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import com.iluwatar.intercepting.filter.App;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -4,75 +4,66 @@ import java.util.Stack;
|
||||
|
||||
/**
|
||||
*
|
||||
* The Interpreter pattern is a design pattern that specifies how to evaluate sentences
|
||||
* in a language. The basic idea is to have a class for each symbol (terminal or nonterminal)
|
||||
* in a specialized computer language. The syntax tree of a sentence in the language is an
|
||||
* instance of the composite pattern and is used to evaluate (interpret) the sentence for a
|
||||
* client.
|
||||
* The Interpreter pattern is a design pattern that specifies how to evaluate sentences in a
|
||||
* language. The basic idea is to have a class for each symbol (terminal or nonterminal) in a
|
||||
* specialized computer language. The syntax tree of a sentence in the language is an instance of
|
||||
* the composite pattern and is used to evaluate (interpret) the sentence for a client.
|
||||
* <p>
|
||||
* In this example we use the Interpreter pattern to break sentences into expressions
|
||||
* ({@link Expression}) that can be evaluated and as a whole form the result.
|
||||
* In this example we use the Interpreter pattern to break sentences into expressions (
|
||||
* {@link Expression}) that can be evaluated and as a whole form the result.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
*
|
||||
* Program entry point.
|
||||
* <p>
|
||||
* Expressions can be evaluated using prefix, infix or postfix notations
|
||||
* This sample uses postfix, where operator comes after the operands
|
||||
*
|
||||
* @param args command line args
|
||||
*
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
String tokenString = "4 3 2 - 1 + *";
|
||||
Stack<Expression> stack = new Stack<>();
|
||||
/**
|
||||
*
|
||||
* Program entry point.
|
||||
* <p>
|
||||
* Expressions can be evaluated using prefix, infix or postfix notations This sample uses postfix,
|
||||
* where operator comes after the operands
|
||||
*
|
||||
* @param args command line args
|
||||
*
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
String tokenString = "4 3 2 - 1 + *";
|
||||
Stack<Expression> stack = new Stack<>();
|
||||
|
||||
String[] tokenList = tokenString.split(" ");
|
||||
for (String s : tokenList) {
|
||||
if (isOperator(s)) {
|
||||
Expression rightExpression = stack.pop();
|
||||
Expression leftExpression = stack.pop();
|
||||
System.out
|
||||
.println(String.format(
|
||||
"popped from stack left: %d right: %d",
|
||||
leftExpression.interpret(),
|
||||
rightExpression.interpret()));
|
||||
Expression operator = getOperatorInstance(s, leftExpression,
|
||||
rightExpression);
|
||||
System.out.println(String.format("operator: %s", operator));
|
||||
int result = operator.interpret();
|
||||
NumberExpression resultExpression = new NumberExpression(result);
|
||||
stack.push(resultExpression);
|
||||
System.out.println(String.format("push result to stack: %d",
|
||||
resultExpression.interpret()));
|
||||
} else {
|
||||
Expression i = new NumberExpression(s);
|
||||
stack.push(i);
|
||||
System.out.println(String.format("push to stack: %d",
|
||||
i.interpret()));
|
||||
}
|
||||
}
|
||||
System.out
|
||||
.println(String.format("result: %d", stack.pop().interpret()));
|
||||
}
|
||||
String[] tokenList = tokenString.split(" ");
|
||||
for (String s : tokenList) {
|
||||
if (isOperator(s)) {
|
||||
Expression rightExpression = stack.pop();
|
||||
Expression leftExpression = stack.pop();
|
||||
System.out.println(String.format("popped from stack left: %d right: %d",
|
||||
leftExpression.interpret(), rightExpression.interpret()));
|
||||
Expression operator = getOperatorInstance(s, leftExpression, rightExpression);
|
||||
System.out.println(String.format("operator: %s", operator));
|
||||
int result = operator.interpret();
|
||||
NumberExpression resultExpression = new NumberExpression(result);
|
||||
stack.push(resultExpression);
|
||||
System.out.println(String.format("push result to stack: %d", resultExpression.interpret()));
|
||||
} else {
|
||||
Expression i = new NumberExpression(s);
|
||||
stack.push(i);
|
||||
System.out.println(String.format("push to stack: %d", i.interpret()));
|
||||
}
|
||||
}
|
||||
System.out.println(String.format("result: %d", stack.pop().interpret()));
|
||||
}
|
||||
|
||||
public static boolean isOperator(String s) {
|
||||
return s.equals("+") || s.equals("-") || s.equals("*");
|
||||
}
|
||||
public static boolean isOperator(String s) {
|
||||
return s.equals("+") || s.equals("-") || s.equals("*");
|
||||
}
|
||||
|
||||
public static Expression getOperatorInstance(String s, Expression left,
|
||||
Expression right) {
|
||||
switch (s) {
|
||||
case "+":
|
||||
return new PlusExpression(left, right);
|
||||
case "-":
|
||||
return new MinusExpression(left, right);
|
||||
case "*":
|
||||
return new MultiplyExpression(left, right);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Expression getOperatorInstance(String s, Expression left, Expression right) {
|
||||
switch (s) {
|
||||
case "+":
|
||||
return new PlusExpression(left, right);
|
||||
case "-":
|
||||
return new MinusExpression(left, right);
|
||||
case "*":
|
||||
return new MultiplyExpression(left, right);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ package com.iluwatar.interpreter;
|
||||
*/
|
||||
public abstract class Expression {
|
||||
|
||||
public abstract int interpret();
|
||||
public abstract int interpret();
|
||||
|
||||
@Override
|
||||
public abstract String toString();
|
||||
@Override
|
||||
public abstract String toString();
|
||||
}
|
||||
|
@ -7,22 +7,22 @@ package com.iluwatar.interpreter;
|
||||
*/
|
||||
public class MinusExpression extends Expression {
|
||||
|
||||
private Expression leftExpression;
|
||||
private Expression rightExpression;
|
||||
private Expression leftExpression;
|
||||
private Expression rightExpression;
|
||||
|
||||
public MinusExpression(Expression leftExpression, Expression rightExpression) {
|
||||
this.leftExpression = leftExpression;
|
||||
this.rightExpression = rightExpression;
|
||||
}
|
||||
public MinusExpression(Expression leftExpression, Expression rightExpression) {
|
||||
this.leftExpression = leftExpression;
|
||||
this.rightExpression = rightExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interpret() {
|
||||
return leftExpression.interpret() - rightExpression.interpret();
|
||||
}
|
||||
@Override
|
||||
public int interpret() {
|
||||
return leftExpression.interpret() - rightExpression.interpret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "-";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "-";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,23 +7,22 @@ package com.iluwatar.interpreter;
|
||||
*/
|
||||
public class MultiplyExpression extends Expression {
|
||||
|
||||
private Expression leftExpression;
|
||||
private Expression rightExpression;
|
||||
private Expression leftExpression;
|
||||
private Expression rightExpression;
|
||||
|
||||
public MultiplyExpression(Expression leftExpression,
|
||||
Expression rightExpression) {
|
||||
this.leftExpression = leftExpression;
|
||||
this.rightExpression = rightExpression;
|
||||
}
|
||||
public MultiplyExpression(Expression leftExpression, Expression rightExpression) {
|
||||
this.leftExpression = leftExpression;
|
||||
this.rightExpression = rightExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interpret() {
|
||||
return leftExpression.interpret() * rightExpression.interpret();
|
||||
}
|
||||
@Override
|
||||
public int interpret() {
|
||||
return leftExpression.interpret() * rightExpression.interpret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "*";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "*";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,24 +7,23 @@ package com.iluwatar.interpreter;
|
||||
*/
|
||||
public class NumberExpression extends Expression {
|
||||
|
||||
private int number;
|
||||
private int number;
|
||||
|
||||
public NumberExpression(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
public NumberExpression(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public NumberExpression(String s) {
|
||||
this.number = Integer.parseInt(s);
|
||||
}
|
||||
public NumberExpression(String s) {
|
||||
this.number = Integer.parseInt(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interpret() {
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "number";
|
||||
}
|
||||
@Override
|
||||
public int interpret() {
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "number";
|
||||
}
|
||||
}
|
||||
|
@ -7,22 +7,21 @@ package com.iluwatar.interpreter;
|
||||
*/
|
||||
public class PlusExpression extends Expression {
|
||||
|
||||
private Expression leftExpression;
|
||||
private Expression rightExpression;
|
||||
private Expression leftExpression;
|
||||
private Expression rightExpression;
|
||||
|
||||
public PlusExpression(Expression leftExpression, Expression rightExpression) {
|
||||
this.leftExpression = leftExpression;
|
||||
this.rightExpression = rightExpression;
|
||||
}
|
||||
public PlusExpression(Expression leftExpression, Expression rightExpression) {
|
||||
this.leftExpression = leftExpression;
|
||||
this.rightExpression = rightExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interpret() {
|
||||
return leftExpression.interpret() + rightExpression.interpret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "+";
|
||||
}
|
||||
@Override
|
||||
public int interpret() {
|
||||
return leftExpression.interpret() + rightExpression.interpret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "+";
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import com.iluwatar.interpreter.App;
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -2,48 +2,48 @@ package com.iluwatar.iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* The Iterator pattern is a design pattern in which an iterator is used to
|
||||
* traverse a container and access the container's elements. The Iterator pattern
|
||||
* decouples algorithms from containers.
|
||||
* The Iterator pattern is a design pattern in which an iterator is used to traverse a container and
|
||||
* access the container's elements. The Iterator pattern decouples algorithms from containers.
|
||||
* <p>
|
||||
* In this example the Iterator ({@link ItemIterator}) adds abstraction layer on
|
||||
* top of a collection ({@link TreasureChest}). This way the collection can change
|
||||
* its internal implementation without affecting its clients.
|
||||
* In this example the Iterator ({@link ItemIterator}) adds abstraction layer on top of a collection
|
||||
* ({@link TreasureChest}). This way the collection can change its internal implementation without
|
||||
* affecting its clients.
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
TreasureChest chest = new TreasureChest();
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
TreasureChest chest = new TreasureChest();
|
||||
|
||||
ItemIterator ringIterator = chest.Iterator(ItemType.RING);
|
||||
while (ringIterator.hasNext()) {
|
||||
System.out.println(ringIterator.next());
|
||||
}
|
||||
ItemIterator ringIterator = chest.Iterator(ItemType.RING);
|
||||
while (ringIterator.hasNext()) {
|
||||
System.out.println(ringIterator.next());
|
||||
}
|
||||
|
||||
System.out.println("----------");
|
||||
System.out.println("----------");
|
||||
|
||||
ItemIterator potionIterator = chest.Iterator(ItemType.POTION);
|
||||
while (potionIterator.hasNext()) {
|
||||
System.out.println(potionIterator.next());
|
||||
}
|
||||
ItemIterator potionIterator = chest.Iterator(ItemType.POTION);
|
||||
while (potionIterator.hasNext()) {
|
||||
System.out.println(potionIterator.next());
|
||||
}
|
||||
|
||||
System.out.println("----------");
|
||||
System.out.println("----------");
|
||||
|
||||
ItemIterator weaponIterator = chest.Iterator(ItemType.WEAPON);
|
||||
while (weaponIterator.hasNext()) {
|
||||
System.out.println(weaponIterator.next());
|
||||
}
|
||||
ItemIterator weaponIterator = chest.Iterator(ItemType.WEAPON);
|
||||
while (weaponIterator.hasNext()) {
|
||||
System.out.println(weaponIterator.next());
|
||||
}
|
||||
|
||||
System.out.println("----------");
|
||||
System.out.println("----------");
|
||||
|
||||
ItemIterator it = chest.Iterator(ItemType.ANY);
|
||||
while (it.hasNext()) {
|
||||
System.out.println(it.next());
|
||||
}
|
||||
}
|
||||
ItemIterator it = chest.Iterator(ItemType.ANY);
|
||||
while (it.hasNext()) {
|
||||
System.out.println(it.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,24 +7,24 @@ package com.iluwatar.iterator;
|
||||
*/
|
||||
public class Item {
|
||||
|
||||
private ItemType type;
|
||||
private String name;
|
||||
private ItemType type;
|
||||
private String name;
|
||||
|
||||
public Item(ItemType type, String name) {
|
||||
this.setType(type);
|
||||
this.name = name;
|
||||
}
|
||||
public Item(ItemType type, String name) {
|
||||
this.setType(type);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ItemType getType() {
|
||||
return type;
|
||||
}
|
||||
public ItemType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(ItemType type) {
|
||||
this.type = type;
|
||||
}
|
||||
public void setType(ItemType type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package com.iluwatar.iterator;
|
||||
*/
|
||||
public interface ItemIterator {
|
||||
|
||||
boolean hasNext();
|
||||
boolean hasNext();
|
||||
|
||||
Item next();
|
||||
Item next();
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ package com.iluwatar.iterator;
|
||||
*/
|
||||
public enum ItemType {
|
||||
|
||||
ANY, WEAPON, RING, POTION
|
||||
ANY, WEAPON, RING, POTION
|
||||
|
||||
}
|
||||
|
@ -10,30 +10,30 @@ import java.util.List;
|
||||
*/
|
||||
public class TreasureChest {
|
||||
|
||||
private List<Item> items;
|
||||
private List<Item> items;
|
||||
|
||||
public TreasureChest() {
|
||||
items = new ArrayList<>();
|
||||
items.add(new Item(ItemType.POTION, "Potion of courage"));
|
||||
items.add(new Item(ItemType.RING, "Ring of shadows"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of wisdom"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of blood"));
|
||||
items.add(new Item(ItemType.WEAPON, "Sword of silver +1"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of rust"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of healing"));
|
||||
items.add(new Item(ItemType.RING, "Ring of armor"));
|
||||
items.add(new Item(ItemType.WEAPON, "Steel halberd"));
|
||||
items.add(new Item(ItemType.WEAPON, "Dagger of poison"));
|
||||
}
|
||||
public TreasureChest() {
|
||||
items = new ArrayList<>();
|
||||
items.add(new Item(ItemType.POTION, "Potion of courage"));
|
||||
items.add(new Item(ItemType.RING, "Ring of shadows"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of wisdom"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of blood"));
|
||||
items.add(new Item(ItemType.WEAPON, "Sword of silver +1"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of rust"));
|
||||
items.add(new Item(ItemType.POTION, "Potion of healing"));
|
||||
items.add(new Item(ItemType.RING, "Ring of armor"));
|
||||
items.add(new Item(ItemType.WEAPON, "Steel halberd"));
|
||||
items.add(new Item(ItemType.WEAPON, "Dagger of poison"));
|
||||
}
|
||||
|
||||
ItemIterator Iterator(ItemType type) {
|
||||
return new TreasureChestItemIterator(this, type);
|
||||
}
|
||||
ItemIterator Iterator(ItemType type) {
|
||||
return new TreasureChestItemIterator(this, type);
|
||||
}
|
||||
|
||||
public List<Item> getItems() {
|
||||
ArrayList<Item> list = new ArrayList<>();
|
||||
list.addAll(items);
|
||||
return list;
|
||||
}
|
||||
public List<Item> getItems() {
|
||||
ArrayList<Item> list = new ArrayList<>();
|
||||
list.addAll(items);
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user