mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-08-05 20:22:43 +00:00
deps: Refactor dependencies (#3224)
* remove spring dep move junit, logging, mockito under dep mgmt * upgrade anti-corruption-layer deps * async method invocation * balking, bloc * bridge to bytecode * caching * callback - cqrs * component - health check * hexagonal - metadata mapping * rest of the patterns * remove checkstyle, take spotless into use
This commit is contained in:
@@ -33,13 +33,14 @@ import com.iluwatar.masterworker.system.systemworkers.Worker;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>The <b><em>Master-Worker</em></b> pattern is used when the problem at hand can be solved by
|
||||
* The <b><em>Master-Worker</em></b> pattern is used when the problem at hand can be solved by
|
||||
* dividing into multiple parts which need to go through the same computation and may need to be
|
||||
* aggregated to get final result. Parallel processing is performed using a system consisting of a
|
||||
* master and some number of workers, where a master divides the work among the workers, gets the
|
||||
* result back from them and assimilates all the results to give final result. The only
|
||||
* communication is between the master and the worker - none of the workers communicate among one
|
||||
* another and the user only communicates with the master to get required job done.</p>
|
||||
* another and the user only communicates with the master to get required job done.
|
||||
*
|
||||
* <p>In our example, we have generic abstract classes {@link MasterWorker}, {@link Master} and
|
||||
* {@link Worker} which have to be extended by the classes which will perform the specific job at
|
||||
* hand (in this case finding transpose of matrix, done by {@link ArrayTransposeMasterWorker},
|
||||
@@ -52,9 +53,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* result. We also have 2 abstract classes {@link Input} and {@link Result}, which contain the input
|
||||
* data and result data respectively. The Input class also has an abstract method divideData which
|
||||
* defines how the data is to be divided into segments. These classes are extended by {@link
|
||||
* ArrayInput} and {@link ArrayResult}.</p>
|
||||
* ArrayInput} and {@link ArrayResult}.
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
public class App {
|
||||
|
||||
@@ -63,7 +63,6 @@ public class App {
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
|
||||
public static void main(String[] args) {
|
||||
var mw = new ArrayTransposeMasterWorker();
|
||||
var rows = 10;
|
||||
@@ -78,5 +77,4 @@ public class App {
|
||||
LOGGER.info("Please enter non-zero input");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,10 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class ArrayInput extends abstract class {@link Input} and contains data of type int[][].
|
||||
*/
|
||||
|
||||
/** Class ArrayInput extends abstract class {@link Input} and contains data of type int[][]. */
|
||||
public class ArrayInput extends Input<int[][]> {
|
||||
|
||||
public ArrayInput(int[][] data) {
|
||||
@@ -39,13 +36,13 @@ public class ArrayInput extends Input<int[][]> {
|
||||
}
|
||||
|
||||
static int[] makeDivisions(int[][] data, int num) {
|
||||
var initialDivision = data.length / num; //equally dividing
|
||||
var initialDivision = data.length / num; // equally dividing
|
||||
var divisions = new int[num];
|
||||
Arrays.fill(divisions, initialDivision);
|
||||
if (initialDivision * num != data.length) {
|
||||
var extra = data.length - initialDivision * num;
|
||||
var l = 0;
|
||||
//equally dividing extra among all parts
|
||||
// equally dividing extra among all parts
|
||||
while (extra > 0) {
|
||||
divisions[l] = divisions[l] + 1;
|
||||
extra--;
|
||||
@@ -66,7 +63,7 @@ public class ArrayInput extends Input<int[][]> {
|
||||
} else {
|
||||
var divisions = makeDivisions(this.data, num);
|
||||
var result = new ArrayList<Input<int[][]>>(num);
|
||||
var rowsDone = 0; //number of rows divided so far
|
||||
var rowsDone = 0; // number of rows divided so far
|
||||
for (var i = 0; i < num; i++) {
|
||||
var rows = divisions[i];
|
||||
if (rows != 0) {
|
||||
@@ -76,7 +73,7 @@ public class ArrayInput extends Input<int[][]> {
|
||||
var dividedInput = new ArrayInput(divided);
|
||||
result.add(dividedInput);
|
||||
} else {
|
||||
break; //rest of divisions will also be 0
|
||||
break; // rest of divisions will also be 0
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -24,10 +24,7 @@
|
||||
*/
|
||||
package com.iluwatar.masterworker;
|
||||
|
||||
/**
|
||||
* Class ArrayResult extends abstract class {@link Result} and contains data of type int[][].
|
||||
*/
|
||||
|
||||
/** Class ArrayResult extends abstract class {@link Result} and contains data of type int[][]. */
|
||||
public class ArrayResult extends Result<int[][]> {
|
||||
|
||||
public ArrayResult(int[][] data) {
|
||||
|
||||
@@ -27,10 +27,7 @@ package com.iluwatar.masterworker;
|
||||
import java.security.SecureRandom;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Class ArrayUtilityMethods has some utility methods for matrices and arrays.
|
||||
*/
|
||||
|
||||
/** Class ArrayUtilityMethods has some utility methods for matrices and arrays. */
|
||||
@Slf4j
|
||||
public class ArrayUtilityMethods {
|
||||
|
||||
@@ -40,9 +37,8 @@ public class ArrayUtilityMethods {
|
||||
* Method arraysSame compares 2 arrays @param a1 and @param a2 and @return whether their values
|
||||
* are equal (boolean).
|
||||
*/
|
||||
|
||||
public static boolean arraysSame(int[] a1, int[] a2) {
|
||||
//compares if 2 arrays have the same value
|
||||
// compares if 2 arrays have the same value
|
||||
if (a1.length != a2.length) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -63,7 +59,6 @@ public class ArrayUtilityMethods {
|
||||
* Method matricesSame compares 2 matrices @param m1 and @param m2 and @return whether their
|
||||
* values are equal (boolean).
|
||||
*/
|
||||
|
||||
public static boolean matricesSame(int[][] m1, int[][] m2) {
|
||||
if (m1.length != m2.length) {
|
||||
return false;
|
||||
@@ -90,19 +85,16 @@ public class ArrayUtilityMethods {
|
||||
var matrix = new int[rows][columns];
|
||||
for (var i = 0; i < rows; i++) {
|
||||
for (var j = 0; j < columns; j++) {
|
||||
//filling cells in matrix
|
||||
// filling cells in matrix
|
||||
matrix[i][j] = RANDOM.nextInt(10);
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method printMatrix prints input matrix @param matrix.
|
||||
*/
|
||||
|
||||
/** Method printMatrix prints input matrix @param matrix. */
|
||||
public static void printMatrix(int[][] matrix) {
|
||||
//prints out int[][]
|
||||
// prints out int[][]
|
||||
for (var ints : matrix) {
|
||||
for (var j = 0; j < matrix[0].length; j++) {
|
||||
LOGGER.info(ints[j] + " ");
|
||||
@@ -110,5 +102,4 @@ public class ArrayUtilityMethods {
|
||||
LOGGER.info("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import java.util.List;
|
||||
*
|
||||
* @param <T> T will be type of data.
|
||||
*/
|
||||
|
||||
public abstract class Input<T> {
|
||||
|
||||
public final T data;
|
||||
|
||||
@@ -29,7 +29,6 @@ package com.iluwatar.masterworker;
|
||||
*
|
||||
* @param <T> T will be type of data.
|
||||
*/
|
||||
|
||||
public abstract class Result<T> {
|
||||
|
||||
public final T data;
|
||||
|
||||
-1
@@ -31,7 +31,6 @@ import com.iluwatar.masterworker.system.systemmaster.Master;
|
||||
* Class ArrayTransposeMasterWorker extends abstract class {@link MasterWorker} and specifically
|
||||
* solves the problem of finding transpose of input array.
|
||||
*/
|
||||
|
||||
public class ArrayTransposeMasterWorker extends MasterWorker {
|
||||
|
||||
public ArrayTransposeMasterWorker() {
|
||||
|
||||
@@ -28,10 +28,7 @@ import com.iluwatar.masterworker.Input;
|
||||
import com.iluwatar.masterworker.Result;
|
||||
import com.iluwatar.masterworker.system.systemmaster.Master;
|
||||
|
||||
/**
|
||||
* The abstract MasterWorker class which contains reference to master.
|
||||
*/
|
||||
|
||||
/** The abstract MasterWorker class which contains reference to master. */
|
||||
public abstract class MasterWorker {
|
||||
private final Master master;
|
||||
|
||||
@@ -46,4 +43,3 @@ public abstract class MasterWorker {
|
||||
return this.master.getFinalResult();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -35,7 +35,6 @@ import java.util.stream.IntStream;
|
||||
* Class ArrayTransposeMaster extends abstract class {@link Master} and contains definition of
|
||||
* aggregateData, which will obtain final result from all data obtained and for setWorkers.
|
||||
*/
|
||||
|
||||
public class ArrayTransposeMaster extends Master {
|
||||
public ArrayTransposeMaster(int numOfWorkers) {
|
||||
super(numOfWorkers);
|
||||
@@ -43,7 +42,7 @@ public class ArrayTransposeMaster extends Master {
|
||||
|
||||
@Override
|
||||
ArrayList<Worker> setWorkers(int num) {
|
||||
//i+1 will be id
|
||||
// i+1 will be id
|
||||
return IntStream.range(0, num)
|
||||
.mapToObj(i -> new ArrayTransposeWorker(this, i + 1))
|
||||
.collect(Collectors.toCollection(() -> new ArrayList<>(num)));
|
||||
@@ -60,20 +59,19 @@ public class ArrayTransposeMaster extends Master {
|
||||
columns += ((ArrayResult) elements.nextElement()).data[0].length;
|
||||
}
|
||||
var resultData = new int[rows][columns];
|
||||
var columnsDone = 0; //columns aggregated so far
|
||||
var columnsDone = 0; // columns aggregated so far
|
||||
var workers = this.getWorkers();
|
||||
for (var i = 0; i < this.getExpectedNumResults(); i++) {
|
||||
//result obtained from ith worker
|
||||
// result obtained from ith worker
|
||||
var worker = workers.get(i);
|
||||
var workerId = worker.getWorkerId();
|
||||
var work = ((ArrayResult) allResultData.get(workerId)).data;
|
||||
for (var m = 0; m < work.length; m++) {
|
||||
//m = row number, n = columns number
|
||||
// m = row number, n = columns number
|
||||
System.arraycopy(work[m], 0, resultData[m], columnsDone, work[0].length);
|
||||
}
|
||||
columnsDone += work[0].length;
|
||||
}
|
||||
return new ArrayResult(resultData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-5
@@ -37,14 +37,12 @@ import lombok.Getter;
|
||||
* number of results), allResultData (hashtable of results obtained from workers, mapped by their
|
||||
* ids) and finalResult (aggregated from allResultData).
|
||||
*/
|
||||
|
||||
public abstract class Master {
|
||||
private final int numOfWorkers;
|
||||
private final List<Worker> workers;
|
||||
private final Hashtable<Integer, Result<?>> allResultData;
|
||||
private int expectedNumResults;
|
||||
@Getter
|
||||
private Result<?> finalResult;
|
||||
@Getter private Result<?> finalResult;
|
||||
|
||||
Master(int numOfWorkers) {
|
||||
this.numOfWorkers = numOfWorkers;
|
||||
@@ -77,7 +75,7 @@ public abstract class Master {
|
||||
if (dividedInput != null) {
|
||||
this.expectedNumResults = dividedInput.size();
|
||||
for (var i = 0; i < this.expectedNumResults; i++) {
|
||||
//ith division given to ith worker in this.workers
|
||||
// ith division given to ith worker in this.workers
|
||||
this.workers.get(i).setReceivedData(this, dividedInput.get(i));
|
||||
this.workers.get(i).start();
|
||||
}
|
||||
@@ -99,7 +97,7 @@ public abstract class Master {
|
||||
private void collectResult(Result<?> data, int workerId) {
|
||||
this.allResultData.put(workerId, data);
|
||||
if (this.allResultData.size() == this.expectedNumResults) {
|
||||
//all data received
|
||||
// all data received
|
||||
this.finalResult = aggregateData();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -32,7 +32,6 @@ import com.iluwatar.masterworker.system.systemmaster.Master;
|
||||
* Class ArrayTransposeWorker extends abstract class {@link Worker} and defines method
|
||||
* executeOperation(), to be performed on data received from master.
|
||||
*/
|
||||
|
||||
public class ArrayTransposeWorker extends Worker {
|
||||
|
||||
public ArrayTransposeWorker(Master master, int id) {
|
||||
@@ -41,14 +40,14 @@ public class ArrayTransposeWorker extends Worker {
|
||||
|
||||
@Override
|
||||
ArrayResult executeOperation() {
|
||||
//number of rows in result matrix is equal to number of columns in input matrix and vice versa
|
||||
// number of rows in result matrix is equal to number of columns in input matrix and vice versa
|
||||
var arrayInput = (ArrayInput) this.getReceivedData();
|
||||
final var rows = arrayInput.data[0].length;
|
||||
final var cols = arrayInput.data.length;
|
||||
var resultData = new int[rows][cols];
|
||||
for (var i = 0; i < cols; i++) {
|
||||
for (var j = 0; j < rows; j++) {
|
||||
//flipping element positions along diagonal
|
||||
// flipping element positions along diagonal
|
||||
resultData[j][i] = arrayInput.data[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -33,11 +33,9 @@ import lombok.Getter;
|
||||
* The abstract Worker class which extends Thread class to enable parallel processing. Contains
|
||||
* fields master(holding reference to master), workerId (unique id) and receivedData(from master).
|
||||
*/
|
||||
|
||||
public abstract class Worker extends Thread {
|
||||
private final Master master;
|
||||
@Getter
|
||||
private final int workerId;
|
||||
@Getter private final int workerId;
|
||||
private Input<?> receivedData;
|
||||
|
||||
Worker(Master master, int id) {
|
||||
@@ -61,7 +59,7 @@ public abstract class Worker extends Thread {
|
||||
this.master.receiveData(data, this);
|
||||
}
|
||||
|
||||
public void run() { //from Thread class
|
||||
public void run() { // from Thread class
|
||||
var work = executeOperation();
|
||||
sendToMaster(work);
|
||||
}
|
||||
|
||||
@@ -30,10 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import java.util.Random;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Testing divideData method in {@link ArrayInput} class.
|
||||
*/
|
||||
|
||||
/** Testing divideData method in {@link ArrayInput} class. */
|
||||
class ArrayInputTest {
|
||||
|
||||
@Test
|
||||
@@ -49,14 +46,14 @@ class ArrayInputTest {
|
||||
}
|
||||
var i = new ArrayInput(inputMatrix);
|
||||
var table = i.divideData(4);
|
||||
var division1 = new int[][]{inputMatrix[0], inputMatrix[1], inputMatrix[2]};
|
||||
var division2 = new int[][]{inputMatrix[3], inputMatrix[4], inputMatrix[5]};
|
||||
var division3 = new int[][]{inputMatrix[6], inputMatrix[7]};
|
||||
var division4 = new int[][]{inputMatrix[8], inputMatrix[9]};
|
||||
assertTrue(matricesSame(table.get(0).data, division1)
|
||||
&& matricesSame(table.get(1).data, division2)
|
||||
&& matricesSame(table.get(2).data, division3)
|
||||
&& matricesSame(table.get(3).data, division4));
|
||||
var division1 = new int[][] {inputMatrix[0], inputMatrix[1], inputMatrix[2]};
|
||||
var division2 = new int[][] {inputMatrix[3], inputMatrix[4], inputMatrix[5]};
|
||||
var division3 = new int[][] {inputMatrix[6], inputMatrix[7]};
|
||||
var division4 = new int[][] {inputMatrix[8], inputMatrix[9]};
|
||||
assertTrue(
|
||||
matricesSame(table.get(0).data, division1)
|
||||
&& matricesSame(table.get(1).data, division2)
|
||||
&& matricesSame(table.get(2).data, division3)
|
||||
&& matricesSame(table.get(3).data, division4));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,24 +28,20 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Testing utility methods in {@link ArrayUtilityMethods} class.
|
||||
*/
|
||||
|
||||
/** Testing utility methods in {@link ArrayUtilityMethods} class. */
|
||||
class ArrayUtilityMethodsTest {
|
||||
|
||||
@Test
|
||||
void arraysSameTest() {
|
||||
var arr1 = new int[]{1, 4, 2, 6};
|
||||
var arr2 = new int[]{1, 4, 2, 6};
|
||||
var arr1 = new int[] {1, 4, 2, 6};
|
||||
var arr2 = new int[] {1, 4, 2, 6};
|
||||
assertTrue(ArrayUtilityMethods.arraysSame(arr1, arr2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void matricesSameTest() {
|
||||
var matrix1 = new int[][]{{1, 4, 2, 6}, {5, 8, 6, 7}};
|
||||
var matrix2 = new int[][]{{1, 4, 2, 6}, {5, 8, 6, 7}};
|
||||
var matrix1 = new int[][] {{1, 4, 2, 6}, {5, 8, 6, 7}};
|
||||
var matrix2 = new int[][] {{1, 4, 2, 6}, {5, 8, 6, 7}};
|
||||
assertTrue(ArrayUtilityMethods.matricesSame(matrix1, matrix2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-18
@@ -31,29 +31,28 @@ import com.iluwatar.masterworker.ArrayResult;
|
||||
import com.iluwatar.masterworker.ArrayUtilityMethods;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Testing getResult method in {@link ArrayTransposeMasterWorker} class.
|
||||
*/
|
||||
|
||||
/** Testing getResult method in {@link ArrayTransposeMasterWorker} class. */
|
||||
class ArrayTransposeMasterWorkerTest {
|
||||
|
||||
@Test
|
||||
void getResultTest() {
|
||||
var atmw = new ArrayTransposeMasterWorker();
|
||||
var matrix = new int[][]{
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5}
|
||||
};
|
||||
var matrixTranspose = new int[][]{
|
||||
{1, 1, 1, 1, 1},
|
||||
{2, 2, 2, 2, 2},
|
||||
{3, 3, 3, 3, 3},
|
||||
{4, 4, 4, 4, 4},
|
||||
{5, 5, 5, 5, 5}
|
||||
};
|
||||
var matrix =
|
||||
new int[][] {
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5}
|
||||
};
|
||||
var matrixTranspose =
|
||||
new int[][] {
|
||||
{1, 1, 1, 1, 1},
|
||||
{2, 2, 2, 2, 2},
|
||||
{3, 3, 3, 3, 3},
|
||||
{4, 4, 4, 4, 4},
|
||||
{5, 5, 5, 5, 5}
|
||||
};
|
||||
var i = new ArrayInput(matrix);
|
||||
var r = (ArrayResult) atmw.getResult(i);
|
||||
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
|
||||
|
||||
+3
-7
@@ -31,22 +31,18 @@ import com.iluwatar.masterworker.ArrayUtilityMethods;
|
||||
import com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Testing executeOperation method in {@link ArrayTransposeWorker} class.
|
||||
*/
|
||||
|
||||
/** Testing executeOperation method in {@link ArrayTransposeWorker} class. */
|
||||
class ArrayTransposeWorkerTest {
|
||||
|
||||
@Test
|
||||
void executeOperationTest() {
|
||||
var atm = new ArrayTransposeMaster(1);
|
||||
var atw = new ArrayTransposeWorker(atm, 1);
|
||||
var matrix = new int[][]{{2, 4}, {3, 5}};
|
||||
var matrixTranspose = new int[][]{{2, 3}, {4, 5}};
|
||||
var matrix = new int[][] {{2, 4}, {3, 5}};
|
||||
var matrixTranspose = new int[][] {{2, 3}, {4, 5}};
|
||||
var i = new ArrayInput(matrix);
|
||||
atw.setReceivedData(atm, i);
|
||||
var r = atw.executeOperation();
|
||||
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user