mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-10-13 22:16:03 +00:00
refactoring: issue#2376 (#2491)
Changed all the switch expression according to the JAVA 17.
This commit is contained in:
1 parent
fc7e672419
commit
9d6ae392b8
23 files changed
+608
-724
No files matched your search
+20
-23
@@ -148,35 +148,32 @@ In this example, we also used an enum to parameterize which type of kingdom fact
|
|||||||
```java
|
```java
|
||||||
public static class FactoryMaker {
|
public static class FactoryMaker {
|
||||||
|
|
||||||
public enum KingdomType {
|
public enum KingdomType {
|
||||||
ELF, ORC
|
ELF, ORC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KingdomFactory makeFactory(KingdomType type) {
|
public static KingdomFactory makeFactory(KingdomType type) {
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case ELF:
|
case ELF -> new ElfKingdomFactory();
|
||||||
return new ElfKingdomFactory();
|
case ORC -> new OrcKingdomFactory();
|
||||||
case ORC:
|
default -> throw new IllegalArgumentException("KingdomType not supported.");
|
||||||
return new OrcKingdomFactory();
|
};
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("KingdomType not supported.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
var app = new App();
|
var app = new App();
|
||||||
|
|
||||||
LOGGER.info("Elf Kingdom");
|
LOGGER.info("Elf Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().getDescription());
|
LOGGER.info(app.getKing().getDescription());
|
||||||
|
|
||||||
LOGGER.info("Orc Kingdom");
|
LOGGER.info("Orc Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||||
-- similar use of the orc factory
|
--similar use of the orc factory
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|||||||
@@ -54,14 +54,11 @@ public class Kingdom {
|
|||||||
* The factory method to create KingdomFactory concrete objects.
|
* The factory method to create KingdomFactory concrete objects.
|
||||||
*/
|
*/
|
||||||
public static KingdomFactory makeFactory(KingdomType type) {
|
public static KingdomFactory makeFactory(KingdomType type) {
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case ELF:
|
case ELF -> new ElfKingdomFactory();
|
||||||
return new ElfKingdomFactory();
|
case ORC -> new OrcKingdomFactory();
|
||||||
case ORC:
|
default -> throw new IllegalArgumentException("KingdomType not supported.");
|
||||||
return new OrcKingdomFactory();
|
};
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("KingdomType not supported.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+116
-117
@@ -163,128 +163,127 @@ remote (costly) service in a circuit breaker object, which prevents faults as fo
|
|||||||
```java
|
```java
|
||||||
public class DefaultCircuitBreaker implements CircuitBreaker {
|
public class DefaultCircuitBreaker implements CircuitBreaker {
|
||||||
|
|
||||||
private final long timeout;
|
private final long timeout;
|
||||||
private final long retryTimePeriod;
|
private final long retryTimePeriod;
|
||||||
private final RemoteService service;
|
private final RemoteService service;
|
||||||
long lastFailureTime;
|
long lastFailureTime;
|
||||||
private String lastFailureResponse;
|
private String lastFailureResponse;
|
||||||
int failureCount;
|
int failureCount;
|
||||||
private final int failureThreshold;
|
private final int failureThreshold;
|
||||||
private State state;
|
private State state;
|
||||||
private final long futureTime = 1000 * 1000 * 1000 * 1000;
|
private final long futureTime = 1000 * 1000 * 1000 * 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor to create an instance of Circuit Breaker.
|
* Constructor to create an instance of Circuit Breaker.
|
||||||
*
|
*
|
||||||
* @param timeout Timeout for the API request. Not necessary for this simple example
|
* @param timeout Timeout for the API request. Not necessary for this simple example
|
||||||
* @param failureThreshold Number of failures we receive from the depended service before changing
|
* @param failureThreshold Number of failures we receive from the depended service before changing
|
||||||
* state to 'OPEN'
|
* state to 'OPEN'
|
||||||
* @param retryTimePeriod Time period after which a new request is made to remote service for
|
* @param retryTimePeriod Time period after which a new request is made to remote service for
|
||||||
* status check.
|
* status check.
|
||||||
*/
|
*/
|
||||||
DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,
|
DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,
|
||||||
long retryTimePeriod) {
|
long retryTimePeriod) {
|
||||||
this.service = serviceToCall;
|
this.service = serviceToCall;
|
||||||
// We start in a closed state hoping that everything is fine
|
// We start in a closed state hoping that everything is fine
|
||||||
this.state = State.CLOSED;
|
this.state = State.CLOSED;
|
||||||
this.failureThreshold = failureThreshold;
|
this.failureThreshold = failureThreshold;
|
||||||
// Timeout for the API request.
|
// Timeout for the API request.
|
||||||
// Used to break the calls made to remote resource if it exceeds the limit
|
// Used to break the calls made to remote resource if it exceeds the limit
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
this.retryTimePeriod = retryTimePeriod;
|
this.retryTimePeriod = retryTimePeriod;
|
||||||
//An absurd amount of time in future which basically indicates the last failure never happened
|
//An absurd amount of time in future which basically indicates the last failure never happened
|
||||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||||
this.failureCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset everything to defaults
|
|
||||||
@Override
|
|
||||||
public void recordSuccess() {
|
|
||||||
this.failureCount = 0;
|
|
||||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
|
||||||
this.state = State.CLOSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recordFailure(String response) {
|
|
||||||
failureCount = failureCount + 1;
|
|
||||||
this.lastFailureTime = System.nanoTime();
|
|
||||||
// Cache the failure response for returning on open state
|
|
||||||
this.lastFailureResponse = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluate the current state based on failureThreshold, failureCount and lastFailureTime.
|
|
||||||
protected void evaluateState() {
|
|
||||||
if (failureCount >= failureThreshold) { //Then something is wrong with remote service
|
|
||||||
if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {
|
|
||||||
//We have waited long enough and should try checking if service is up
|
|
||||||
state = State.HALF_OPEN;
|
|
||||||
} else {
|
|
||||||
//Service would still probably be down
|
|
||||||
state = State.OPEN;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Everything is working fine
|
|
||||||
state = State.CLOSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getState() {
|
|
||||||
evaluateState();
|
|
||||||
return state.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Break the circuit beforehand if it is known service is down Or connect the circuit manually if
|
|
||||||
* service comes online before expected.
|
|
||||||
*
|
|
||||||
* @param state State at which circuit is in
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setState(State state) {
|
|
||||||
this.state = state;
|
|
||||||
switch (state) {
|
|
||||||
case OPEN:
|
|
||||||
this.failureCount = failureThreshold;
|
|
||||||
this.lastFailureTime = System.nanoTime();
|
|
||||||
break;
|
|
||||||
case HALF_OPEN:
|
|
||||||
this.failureCount = failureThreshold;
|
|
||||||
this.lastFailureTime = System.nanoTime() - retryTimePeriod;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.failureCount = 0;
|
this.failureCount = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Reset everything to defaults
|
||||||
* Executes service call.
|
@Override
|
||||||
*
|
public void recordSuccess() {
|
||||||
* @return Value from the remote resource, stale response or a custom exception
|
this.failureCount = 0;
|
||||||
*/
|
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||||
@Override
|
this.state = State.CLOSED;
|
||||||
public String attemptRequest() throws RemoteServiceException {
|
}
|
||||||
evaluateState();
|
|
||||||
if (state == State.OPEN) {
|
@Override
|
||||||
// return cached response if the circuit is in OPEN state
|
public void recordFailure(String response) {
|
||||||
return this.lastFailureResponse;
|
failureCount = failureCount + 1;
|
||||||
} else {
|
this.lastFailureTime = System.nanoTime();
|
||||||
// Make the API request if the circuit is not OPEN
|
// Cache the failure response for returning on open state
|
||||||
try {
|
this.lastFailureResponse = response;
|
||||||
//In a real application, this would be run in a thread and the timeout
|
}
|
||||||
//parameter of the circuit breaker would be utilized to know if service
|
|
||||||
//is working. Here, we simulate that based on server response itself
|
// Evaluate the current state based on failureThreshold, failureCount and lastFailureTime.
|
||||||
var response = service.call();
|
protected void evaluateState() {
|
||||||
// Yay!! the API responded fine. Let's reset everything.
|
if (failureCount >= failureThreshold) { //Then something is wrong with remote service
|
||||||
recordSuccess();
|
if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {
|
||||||
return response;
|
//We have waited long enough and should try checking if service is up
|
||||||
} catch (RemoteServiceException ex) {
|
state = State.HALF_OPEN;
|
||||||
recordFailure(ex.getMessage());
|
} else {
|
||||||
throw ex;
|
//Service would still probably be down
|
||||||
}
|
state = State.OPEN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Everything is working fine
|
||||||
|
state = State.CLOSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getState() {
|
||||||
|
evaluateState();
|
||||||
|
return state.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break the circuit beforehand if it is known service is down Or connect the circuit manually if
|
||||||
|
* service comes online before expected.
|
||||||
|
*
|
||||||
|
* @param state State at which circuit is in
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setState(State state) {
|
||||||
|
this.state = state;
|
||||||
|
switch (state) {
|
||||||
|
case OPEN -> {
|
||||||
|
this.failureCount = failureThreshold;
|
||||||
|
this.lastFailureTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
case HALF_OPEN -> {
|
||||||
|
this.failureCount = failureThreshold;
|
||||||
|
this.lastFailureTime = System.nanoTime() - retryTimePeriod;
|
||||||
|
}
|
||||||
|
default -> this.failureCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes service call.
|
||||||
|
*
|
||||||
|
* @return Value from the remote resource, stale response or a custom exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String attemptRequest() throws RemoteServiceException {
|
||||||
|
evaluateState();
|
||||||
|
if (state == State.OPEN) {
|
||||||
|
// return cached response if the circuit is in OPEN state
|
||||||
|
return this.lastFailureResponse;
|
||||||
|
} else {
|
||||||
|
// Make the API request if the circuit is not OPEN
|
||||||
|
try {
|
||||||
|
//In a real application, this would be run in a thread and the timeout
|
||||||
|
//parameter of the circuit breaker would be utilized to know if service
|
||||||
|
//is working. Here, we simulate that based on server response itself
|
||||||
|
var response = service.call();
|
||||||
|
// Yay!! the API responded fine. Let's reset everything.
|
||||||
|
recordSuccess();
|
||||||
|
return response;
|
||||||
|
} catch (RemoteServiceException ex) {
|
||||||
|
recordFailure(ex.getMessage());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+5
-6
@@ -113,16 +113,15 @@ public class DefaultCircuitBreaker implements CircuitBreaker {
|
|||||||
public void setState(State state) {
|
public void setState(State state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case OPEN:
|
case OPEN -> {
|
||||||
this.failureCount = failureThreshold;
|
this.failureCount = failureThreshold;
|
||||||
this.lastFailureTime = System.nanoTime();
|
this.lastFailureTime = System.nanoTime();
|
||||||
break;
|
}
|
||||||
case HALF_OPEN:
|
case HALF_OPEN -> {
|
||||||
this.failureCount = failureThreshold;
|
this.failureCount = failureThreshold;
|
||||||
this.lastFailureTime = System.nanoTime() - retryTimePeriod;
|
this.lastFailureTime = System.nanoTime() - retryTimePeriod;
|
||||||
break;
|
}
|
||||||
default:
|
default -> this.failureCount = 0;
|
||||||
this.failureCount = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -21,18 +21,18 @@ public class PlayerInputComponent implements InputComponent {
|
|||||||
@Override
|
@Override
|
||||||
public void update(GameObject gameObject, int e) {
|
public void update(GameObject gameObject, int e) {
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case KeyEvent.KEY_LOCATION_LEFT:
|
case KeyEvent.KEY_LOCATION_LEFT -> {
|
||||||
gameObject.updateVelocity(-WALK_ACCELERATION);
|
gameObject.updateVelocity(-WALK_ACCELERATION);
|
||||||
LOGGER.info(gameObject.getName() + " has moved left.");
|
LOGGER.info(gameObject.getName() + " has moved left.");
|
||||||
break;
|
}
|
||||||
case KeyEvent.KEY_LOCATION_RIGHT:
|
case KeyEvent.KEY_LOCATION_RIGHT -> {
|
||||||
gameObject.updateVelocity(WALK_ACCELERATION);
|
gameObject.updateVelocity(WALK_ACCELERATION);
|
||||||
LOGGER.info(gameObject.getName() + " has moved right.");
|
LOGGER.info(gameObject.getName() + " has moved right.");
|
||||||
break;
|
}
|
||||||
default:
|
default -> {
|
||||||
LOGGER.info(gameObject.getName() + "'s velocity is unchanged due to the invalid input");
|
LOGGER.info(gameObject.getName() + "'s velocity is unchanged due to the invalid input");
|
||||||
gameObject.updateVelocity(0);
|
gameObject.updateVelocity(0);
|
||||||
break; // incorrect input
|
} // incorrect input
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+34
-45
@@ -36,59 +36,48 @@ Let's take our goldmine example from above. Here we have the dwarven mine worker
|
|||||||
there's a base class `DwarvenMineWorker`:
|
there's a base class `DwarvenMineWorker`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class DwarvenMineWorker {
|
public abstract class DwarvenMineWorker {
|
||||||
|
|
||||||
public void goToSleep() {
|
public void goToSleep() {
|
||||||
LOGGER.info("{} goes to sleep.", name());
|
LOGGER.info("{} goes to sleep.", name());
|
||||||
}
|
|
||||||
|
|
||||||
public void wakeUp() {
|
|
||||||
LOGGER.info("{} wakes up.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goHome() {
|
|
||||||
LOGGER.info("{} goes home.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goToMine() {
|
|
||||||
LOGGER.info("{} goes to the mine.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
LOGGER.info("Undefined action");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void action(Action... actions) {
|
public void wakeUp() {
|
||||||
Arrays.stream(actions).forEach(this::action);
|
LOGGER.info("{} wakes up.", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void work();
|
public void goHome() {
|
||||||
|
LOGGER.info("{} goes home.", name());
|
||||||
|
}
|
||||||
|
|
||||||
public abstract String name();
|
public void goToMine() {
|
||||||
|
LOGGER.info("{} goes to the mine.", name());
|
||||||
|
}
|
||||||
|
|
||||||
enum Action {
|
private void action(Action action) {
|
||||||
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
switch (action) {
|
||||||
}
|
case GO_TO_SLEEP -> goToSleep();
|
||||||
|
case WAKE_UP -> wakeUp();
|
||||||
|
case GO_HOME -> goHome();
|
||||||
|
case GO_TO_MINE -> goToMine();
|
||||||
|
case WORK -> work();
|
||||||
|
default -> LOGGER.info("Undefined action");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void action(Action... actions) {
|
||||||
|
Arrays.stream(actions).forEach(this::action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void work();
|
||||||
|
|
||||||
|
public abstract String name();
|
||||||
|
|
||||||
|
enum Action {
|
||||||
|
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -51,24 +51,12 @@ public abstract class DwarvenMineWorker {
|
|||||||
|
|
||||||
private void action(Action action) {
|
private void action(Action action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case GO_TO_SLEEP:
|
case GO_TO_SLEEP -> goToSleep();
|
||||||
goToSleep();
|
case WAKE_UP -> wakeUp();
|
||||||
break;
|
case GO_HOME -> goHome();
|
||||||
case WAKE_UP:
|
case GO_TO_MINE -> goToMine();
|
||||||
wakeUp();
|
case WORK -> work();
|
||||||
break;
|
default -> LOGGER.info("Undefined action");
|
||||||
case GO_HOME:
|
|
||||||
goHome();
|
|
||||||
break;
|
|
||||||
case GO_TO_MINE:
|
|
||||||
goToMine();
|
|
||||||
break;
|
|
||||||
case WORK:
|
|
||||||
work();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOGGER.info("Undefined action");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -80,20 +80,20 @@ public class PotionFactory {
|
|||||||
var potion = potions.get(type);
|
var potion = potions.get(type);
|
||||||
if (potion == null) {
|
if (potion == null) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case HEALING:
|
case HEALING -> {
|
||||||
potion = new HealingPotion();
|
potion = new HealingPotion();
|
||||||
potions.put(type, potion);
|
potions.put(type, potion);
|
||||||
break;
|
}
|
||||||
case HOLY_WATER:
|
case HOLY_WATER -> {
|
||||||
potion = new HolyWaterPotion();
|
potion = new HolyWaterPotion();
|
||||||
potions.put(type, potion);
|
potions.put(type, potion);
|
||||||
break;
|
}
|
||||||
case INVISIBILITY:
|
case INVISIBILITY -> {
|
||||||
potion = new InvisibilityPotion();
|
potion = new InvisibilityPotion();
|
||||||
potions.put(type, potion);
|
potions.put(type, potion);
|
||||||
break;
|
}
|
||||||
default:
|
default -> {
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return potion;
|
return potion;
|
||||||
|
|||||||
@@ -44,23 +44,13 @@ public class PotionFactory {
|
|||||||
var potion = potions.get(type);
|
var potion = potions.get(type);
|
||||||
if (potion == null) {
|
if (potion == null) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case HEALING:
|
case HEALING -> potion = new HealingPotion();
|
||||||
potion = new HealingPotion();
|
case HOLY_WATER -> potion = new HolyWaterPotion();
|
||||||
break;
|
case INVISIBILITY -> potion = new InvisibilityPotion();
|
||||||
case HOLY_WATER:
|
case POISON -> potion = new PoisonPotion();
|
||||||
potion = new HolyWaterPotion();
|
case STRENGTH -> potion = new StrengthPotion();
|
||||||
break;
|
default -> {
|
||||||
case INVISIBILITY:
|
}
|
||||||
potion = new InvisibilityPotion();
|
|
||||||
break;
|
|
||||||
case POISON:
|
|
||||||
potion = new PoisonPotion();
|
|
||||||
break;
|
|
||||||
case STRENGTH:
|
|
||||||
potion = new StrengthPotion();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (potion != null) {
|
if (potion != null) {
|
||||||
potions.put(type, potion);
|
potions.put(type, potion);
|
||||||
|
|||||||
@@ -101,13 +101,10 @@ public class App {
|
|||||||
* @return expression
|
* @return expression
|
||||||
*/
|
*/
|
||||||
public static Expression getOperatorInstance(String s, Expression left, Expression right) {
|
public static Expression getOperatorInstance(String s, Expression left, Expression right) {
|
||||||
switch (s) {
|
return switch (s) {
|
||||||
case "+":
|
case "+" -> new PlusExpression(left, right);
|
||||||
return new PlusExpression(left, right);
|
case "-" -> new MinusExpression(left, right);
|
||||||
case "-":
|
default -> new MultiplyExpression(left, right);
|
||||||
return new MinusExpression(left, right);
|
};
|
||||||
default:
|
|
||||||
return new MultiplyExpression(left, right);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,32 +105,32 @@ public abstract class AbstractInstance implements Instance, Runnable {
|
|||||||
*/
|
*/
|
||||||
private void processMessage(Message message) {
|
private void processMessage(Message message) {
|
||||||
switch (message.getType()) {
|
switch (message.getType()) {
|
||||||
case ELECTION:
|
case ELECTION -> {
|
||||||
LOGGER.info(INSTANCE + localId + " - Election Message handling...");
|
LOGGER.info(INSTANCE + localId + " - Election Message handling...");
|
||||||
handleElectionMessage(message);
|
handleElectionMessage(message);
|
||||||
break;
|
}
|
||||||
case LEADER:
|
case LEADER -> {
|
||||||
LOGGER.info(INSTANCE + localId + " - Leader Message handling...");
|
LOGGER.info(INSTANCE + localId + " - Leader Message handling...");
|
||||||
handleLeaderMessage(message);
|
handleLeaderMessage(message);
|
||||||
break;
|
}
|
||||||
case HEARTBEAT:
|
case HEARTBEAT -> {
|
||||||
LOGGER.info(INSTANCE + localId + " - Heartbeat Message handling...");
|
LOGGER.info(INSTANCE + localId + " - Heartbeat Message handling...");
|
||||||
handleHeartbeatMessage(message);
|
handleHeartbeatMessage(message);
|
||||||
break;
|
}
|
||||||
case ELECTION_INVOKE:
|
case ELECTION_INVOKE -> {
|
||||||
LOGGER.info(INSTANCE + localId + " - Election Invoke Message handling...");
|
LOGGER.info(INSTANCE + localId + " - Election Invoke Message handling...");
|
||||||
handleElectionInvokeMessage();
|
handleElectionInvokeMessage();
|
||||||
break;
|
}
|
||||||
case LEADER_INVOKE:
|
case LEADER_INVOKE -> {
|
||||||
LOGGER.info(INSTANCE + localId + " - Leader Invoke Message handling...");
|
LOGGER.info(INSTANCE + localId + " - Leader Invoke Message handling...");
|
||||||
handleLeaderInvokeMessage();
|
handleLeaderInvokeMessage();
|
||||||
break;
|
}
|
||||||
case HEARTBEAT_INVOKE:
|
case HEARTBEAT_INVOKE -> {
|
||||||
LOGGER.info(INSTANCE + localId + " - Heartbeat Invoke Message handling...");
|
LOGGER.info(INSTANCE + localId + " - Heartbeat Invoke Message handling...");
|
||||||
handleHeartbeatInvokeMessage();
|
handleHeartbeatInvokeMessage();
|
||||||
break;
|
}
|
||||||
default:
|
default -> {
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,35 +150,32 @@ En este ejemplo también usamos un enum para parametrizar el tipo de factoría d
|
|||||||
```java
|
```java
|
||||||
public static class FactoryMaker {
|
public static class FactoryMaker {
|
||||||
|
|
||||||
public enum KingdomType {
|
public enum KingdomType {
|
||||||
ELF, ORC
|
ELF, ORC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KingdomFactory makeFactory(KingdomType type) {
|
public static KingdomFactory makeFactory(KingdomType type) {
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case ELF:
|
case ELF -> new ElfKingdomFactory();
|
||||||
return new ElfKingdomFactory();
|
case ORC -> new OrcKingdomFactory();
|
||||||
case ORC:
|
default -> throw new IllegalArgumentException("KingdomType not supported.");
|
||||||
return new OrcKingdomFactory();
|
};
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("KingdomType not supported.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
var app = new App();
|
var app = new App();
|
||||||
|
|
||||||
LOGGER.info("Elf Kingdom");
|
LOGGER.info("Elf Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().getDescription());
|
LOGGER.info(app.getKing().getDescription());
|
||||||
|
|
||||||
LOGGER.info("Orc Kingdom");
|
LOGGER.info("Orc Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||||
-- similar use of the orc factory
|
--similar use of the orc factory
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Diagrama de clases
|
## Diagrama de clases
|
||||||
|
|||||||
@@ -148,35 +148,32 @@ This is the elven Army!
|
|||||||
```java
|
```java
|
||||||
public static class FactoryMaker {
|
public static class FactoryMaker {
|
||||||
|
|
||||||
public enum KingdomType {
|
public enum KingdomType {
|
||||||
ELF, ORC
|
ELF, ORC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KingdomFactory makeFactory(KingdomType type) {
|
public static KingdomFactory makeFactory(KingdomType type) {
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case ELF:
|
case ELF -> new ElfKingdomFactory();
|
||||||
return new ElfKingdomFactory();
|
case ORC -> new OrcKingdomFactory();
|
||||||
case ORC:
|
default -> throw new IllegalArgumentException("KingdomType not supported.");
|
||||||
return new OrcKingdomFactory();
|
};
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("KingdomType not supported.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
var app = new App();
|
var app = new App();
|
||||||
|
|
||||||
LOGGER.info("Elf Kingdom");
|
LOGGER.info("Elf Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().getDescription());
|
LOGGER.info(app.getKing().getDescription());
|
||||||
|
|
||||||
LOGGER.info("Orc Kingdom");
|
LOGGER.info("Orc Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||||
-- similar use of the orc factory
|
--similar use of the orc factory
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## क्लास डायग्राम
|
## क्लास डायग्राम
|
||||||
|
|||||||
@@ -145,39 +145,35 @@ Agora, podemos projetar uma fábrica para nossas diferentes fábricas do reino.
|
|||||||
O cliente pode usar o `FactoryMaker` para criar uma fatoração concreta, que uma vez, produzirá diferentes objetos concretos (derivados de `Army`, `King`, `Castle`).
|
O cliente pode usar o `FactoryMaker` para criar uma fatoração concreta, que uma vez, produzirá diferentes objetos concretos (derivados de `Army`, `King`, `Castle`).
|
||||||
Neste exemplo, também usamos um enum para parametrizar qual tipo de fábrica do reino o cliente solicitará.
|
Neste exemplo, também usamos um enum para parametrizar qual tipo de fábrica do reino o cliente solicitará.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public static class FactoryMaker {
|
public static class FactoryMaker {
|
||||||
|
|
||||||
public enum KingdomType {
|
public enum KingdomType {
|
||||||
ELF, ORC
|
ELF, ORC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KingdomFactory makeFactory(KingdomType type) {
|
public static KingdomFactory makeFactory(KingdomType type) {
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case ELF:
|
case ELF -> new ElfKingdomFactory();
|
||||||
return new ElfKingdomFactory();
|
case ORC -> new OrcKingdomFactory();
|
||||||
case ORC:
|
default -> throw new IllegalArgumentException("KingdomType not supported.");
|
||||||
return new OrcKingdomFactory();
|
};
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("KingdomType not supported.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
var app = new App();
|
var app = new App();
|
||||||
|
|
||||||
LOGGER.info("Elf Kingdom");
|
LOGGER.info("Elf Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().getDescription());
|
LOGGER.info(app.getKing().getDescription());
|
||||||
|
|
||||||
LOGGER.info("Orc Kingdom");
|
LOGGER.info("Orc Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||||
-- similar use of the orc factory
|
--similar use of the orc factory
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Diagrama de classes
|
## Diagrama de classes
|
||||||
|
|||||||
@@ -34,62 +34,51 @@ Wikipedia diz
|
|||||||
**Exemplo programático**
|
**Exemplo programático**
|
||||||
|
|
||||||
Vamos pegar nosso exemplo da mina de ouro acima. Aqui temos uma hierarquia de anão minerador.
|
Vamos pegar nosso exemplo da mina de ouro acima. Aqui temos uma hierarquia de anão minerador.
|
||||||
Primeiro há uma classe base `DwarvenMineWorker`:
|
Primeiro há uma classe base `DwarvenMineWorker`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class DwarvenMineWorker {
|
public abstract class DwarvenMineWorker {
|
||||||
|
|
||||||
public void goToSleep() {
|
public void goToSleep() {
|
||||||
LOGGER.info("{} goes to sleep.", name());
|
LOGGER.info("{} goes to sleep.", name());
|
||||||
}
|
|
||||||
|
|
||||||
public void wakeUp() {
|
|
||||||
LOGGER.info("{} wakes up.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goHome() {
|
|
||||||
LOGGER.info("{} goes home.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goToMine() {
|
|
||||||
LOGGER.info("{} goes to the mine.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
LOGGER.info("Undefined action");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void action(Action... actions) {
|
public void wakeUp() {
|
||||||
Arrays.stream(actions).forEach(this::action);
|
LOGGER.info("{} wakes up.", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void work();
|
public void goHome() {
|
||||||
|
LOGGER.info("{} goes home.", name());
|
||||||
|
}
|
||||||
|
|
||||||
public abstract String name();
|
public void goToMine() {
|
||||||
|
LOGGER.info("{} goes to the mine.", name());
|
||||||
|
}
|
||||||
|
|
||||||
enum Action {
|
private void action(Action action) {
|
||||||
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
switch (action) {
|
||||||
}
|
case GO_TO_SLEEP -> goToSleep();
|
||||||
|
case WAKE_UP -> wakeUp();
|
||||||
|
case GO_HOME -> goHome();
|
||||||
|
case GO_TO_MINE -> goToMine();
|
||||||
|
case WORK -> work();
|
||||||
|
default -> LOGGER.info("Undefined action");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void action(Action... actions) {
|
||||||
|
Arrays.stream(actions).forEach(this::action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void work();
|
||||||
|
|
||||||
|
public abstract String name();
|
||||||
|
|
||||||
|
enum Action {
|
||||||
|
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -150,35 +150,32 @@ Trong ví dụ này, chúng tôi cũng sử dụng một enum để tham số h
|
|||||||
```java
|
```java
|
||||||
public static class FactoryMaker {
|
public static class FactoryMaker {
|
||||||
|
|
||||||
public enum KingdomType {
|
public enum KingdomType {
|
||||||
ELF, ORC
|
ELF, ORC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KingdomFactory makeFactory(KingdomType type) {
|
public static KingdomFactory makeFactory(KingdomType type) {
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case ELF:
|
case ELF -> new ElfKingdomFactory();
|
||||||
return new ElfKingdomFactory();
|
case ORC -> new OrcKingdomFactory();
|
||||||
case ORC:
|
default -> throw new IllegalArgumentException("KingdomType not supported.");
|
||||||
return new OrcKingdomFactory();
|
};
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("KingdomType not supported.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
var app = new App();
|
var app = new App();
|
||||||
|
|
||||||
LOGGER.info("Elf Kingdom");
|
LOGGER.info("Elf Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().getDescription());
|
LOGGER.info(app.getKing().getDescription());
|
||||||
|
|
||||||
LOGGER.info("Orc Kingdom");
|
LOGGER.info("Orc Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||||
-- Tương tự với nhà máy Orc
|
--Tương tự với nhà máy Orc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sơ đồ lớp
|
## Sơ đồ lớp
|
||||||
|
|||||||
@@ -132,35 +132,32 @@ This is the Elven Army!
|
|||||||
```java
|
```java
|
||||||
public static class FactoryMaker {
|
public static class FactoryMaker {
|
||||||
|
|
||||||
public enum KingdomType {
|
public enum KingdomType {
|
||||||
ELF, ORC
|
ELF, ORC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KingdomFactory makeFactory(KingdomType type) {
|
public static KingdomFactory makeFactory(KingdomType type) {
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case ELF:
|
case ELF -> new ElfKingdomFactory();
|
||||||
return new ElfKingdomFactory();
|
case ORC -> new OrcKingdomFactory();
|
||||||
case ORC:
|
default -> throw new IllegalArgumentException("KingdomType not supported.");
|
||||||
return new OrcKingdomFactory();
|
};
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("KingdomType not supported.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
var app = new App();
|
var app = new App();
|
||||||
|
|
||||||
LOGGER.info("Elf Kingdom");
|
LOGGER.info("Elf Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().getDescription());
|
LOGGER.info(app.getKing().getDescription());
|
||||||
|
|
||||||
LOGGER.info("Orc Kingdom");
|
LOGGER.info("Orc Kingdom");
|
||||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||||
-- similar use of the orc factory
|
--similar use of the orc factory
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 类图
|
## 类图
|
||||||
|
|||||||
@@ -152,127 +152,126 @@ public class MonitoringService {
|
|||||||
```java
|
```java
|
||||||
public class DefaultCircuitBreaker implements CircuitBreaker {
|
public class DefaultCircuitBreaker implements CircuitBreaker {
|
||||||
|
|
||||||
private final long timeout;
|
private final long timeout;
|
||||||
private final long retryTimePeriod;
|
private final long retryTimePeriod;
|
||||||
private final RemoteService service;
|
private final RemoteService service;
|
||||||
long lastFailureTime;
|
long lastFailureTime;
|
||||||
private String lastFailureResponse;
|
private String lastFailureResponse;
|
||||||
int failureCount;
|
int failureCount;
|
||||||
private final int failureThreshold;
|
private final int failureThreshold;
|
||||||
private State state;
|
private State state;
|
||||||
private final long futureTime = 1000 * 1000 * 1000 * 1000;
|
private final long futureTime = 1000 * 1000 * 1000 * 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor to create an instance of Circuit Breaker.
|
* Constructor to create an instance of Circuit Breaker.
|
||||||
*
|
*
|
||||||
* @param timeout Timeout for the API request. Not necessary for this simple example
|
* @param timeout Timeout for the API request. Not necessary for this simple example
|
||||||
* @param failureThreshold Number of failures we receive from the depended service before changing
|
* @param failureThreshold Number of failures we receive from the depended service before changing
|
||||||
* state to 'OPEN'
|
* state to 'OPEN'
|
||||||
* @param retryTimePeriod Time period after which a new request is made to remote service for
|
* @param retryTimePeriod Time period after which a new request is made to remote service for
|
||||||
* status check.
|
* status check.
|
||||||
*/
|
*/
|
||||||
DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,
|
DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,
|
||||||
long retryTimePeriod) {
|
long retryTimePeriod) {
|
||||||
this.service = serviceToCall;
|
this.service = serviceToCall;
|
||||||
// 我们从关闭状态开始希望一切都是正常的
|
// 我们从关闭状态开始希望一切都是正常的
|
||||||
this.state = State.CLOSED;
|
this.state = State.CLOSED;
|
||||||
this.failureThreshold = failureThreshold;
|
this.failureThreshold = failureThreshold;
|
||||||
// API的超时时间.
|
// API的超时时间.
|
||||||
// 用于在超过限制时中断对远程资源的调用
|
// 用于在超过限制时中断对远程资源的调用
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
this.retryTimePeriod = retryTimePeriod;
|
this.retryTimePeriod = retryTimePeriod;
|
||||||
//An absurd amount of time in future which basically indicates the last failure never happened
|
//An absurd amount of time in future which basically indicates the last failure never happened
|
||||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||||
this.failureCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置所有
|
|
||||||
@Override
|
|
||||||
public void recordSuccess() {
|
|
||||||
this.failureCount = 0;
|
|
||||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
|
||||||
this.state = State.CLOSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recordFailure(String response) {
|
|
||||||
failureCount = failureCount + 1;
|
|
||||||
this.lastFailureTime = System.nanoTime();
|
|
||||||
// Cache the failure response for returning on open state
|
|
||||||
this.lastFailureResponse = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据 failureThreshold、failureCount 和 lastFailureTime 评估当前状态。
|
|
||||||
protected void evaluateState() {
|
|
||||||
if (failureCount >= failureThreshold) { //Then something is wrong with remote service
|
|
||||||
if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {
|
|
||||||
// 我们已经等得够久了,应该尝试检查服务是否已启动
|
|
||||||
state = State.HALF_OPEN;
|
|
||||||
} else {
|
|
||||||
// 服务可能仍会出现故障
|
|
||||||
state = State.OPEN;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 一切正常
|
|
||||||
state = State.CLOSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getState() {
|
|
||||||
evaluateState();
|
|
||||||
return state.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Break the circuit beforehand if it is known service is down Or connect the circuit manually if
|
|
||||||
* service comes online before expected.
|
|
||||||
*
|
|
||||||
* @param state State at which circuit is in
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setState(State state) {
|
|
||||||
this.state = state;
|
|
||||||
switch (state) {
|
|
||||||
case OPEN:
|
|
||||||
this.failureCount = failureThreshold;
|
|
||||||
this.lastFailureTime = System.nanoTime();
|
|
||||||
break;
|
|
||||||
case HALF_OPEN:
|
|
||||||
this.failureCount = failureThreshold;
|
|
||||||
this.lastFailureTime = System.nanoTime() - retryTimePeriod;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.failureCount = 0;
|
this.failureCount = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// 重置所有
|
||||||
* Executes service call.
|
@Override
|
||||||
*
|
public void recordSuccess() {
|
||||||
* @return Value from the remote resource, stale response or a custom exception
|
this.failureCount = 0;
|
||||||
*/
|
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||||
@Override
|
this.state = State.CLOSED;
|
||||||
public String attemptRequest() throws RemoteServiceException {
|
}
|
||||||
evaluateState();
|
|
||||||
if (state == State.OPEN) {
|
@Override
|
||||||
// 如果电路处于打开状态,则返回缓存的响应
|
public void recordFailure(String response) {
|
||||||
return this.lastFailureResponse;
|
failureCount = failureCount + 1;
|
||||||
} else {
|
this.lastFailureTime = System.nanoTime();
|
||||||
// 如果电路未打开,则发出 API 请求
|
// Cache the failure response for returning on open state
|
||||||
try {
|
this.lastFailureResponse = response;
|
||||||
//在实际应用程序中,这将在线程中运行,并且将利用断路器的超时参数来了解服务
|
}
|
||||||
// 是否正在工作。 在这里,我们根据服务器响应本身模拟
|
|
||||||
var response = service.call();
|
// 根据 failureThreshold、failureCount 和 lastFailureTime 评估当前状态。
|
||||||
// api 响应正常,重置所有。
|
protected void evaluateState() {
|
||||||
recordSuccess();
|
if (failureCount >= failureThreshold) { //Then something is wrong with remote service
|
||||||
return response;
|
if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {
|
||||||
} catch (RemoteServiceException ex) {
|
// 我们已经等得够久了,应该尝试检查服务是否已启动
|
||||||
recordFailure(ex.getMessage());
|
state = State.HALF_OPEN;
|
||||||
throw ex;
|
} else {
|
||||||
}
|
// 服务可能仍会出现故障
|
||||||
|
state = State.OPEN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 一切正常
|
||||||
|
state = State.CLOSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getState() {
|
||||||
|
evaluateState();
|
||||||
|
return state.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break the circuit beforehand if it is known service is down Or connect the circuit manually if
|
||||||
|
* service comes online before expected.
|
||||||
|
*
|
||||||
|
* @param state State at which circuit is in
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setState(State state) {
|
||||||
|
this.state = state;
|
||||||
|
switch (state) {
|
||||||
|
case OPEN -> {
|
||||||
|
this.failureCount = failureThreshold;
|
||||||
|
this.lastFailureTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
case HALF_OPEN -> {
|
||||||
|
this.failureCount = failureThreshold;
|
||||||
|
this.lastFailureTime = System.nanoTime() - retryTimePeriod;
|
||||||
|
}
|
||||||
|
default -> this.failureCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes service call.
|
||||||
|
*
|
||||||
|
* @return Value from the remote resource, stale response or a custom exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String attemptRequest() throws RemoteServiceException {
|
||||||
|
evaluateState();
|
||||||
|
if (state == State.OPEN) {
|
||||||
|
// 如果电路处于打开状态,则返回缓存的响应
|
||||||
|
return this.lastFailureResponse;
|
||||||
|
} else {
|
||||||
|
// 如果电路未打开,则发出 API 请求
|
||||||
|
try {
|
||||||
|
//在实际应用程序中,这将在线程中运行,并且将利用断路器的超时参数来了解服务
|
||||||
|
// 是否正在工作。 在这里,我们根据服务器响应本身模拟
|
||||||
|
var response = service.call();
|
||||||
|
// api 响应正常,重置所有。
|
||||||
|
recordSuccess();
|
||||||
|
return response;
|
||||||
|
} catch (RemoteServiceException ex) {
|
||||||
|
recordFailure(ex.getMessage());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -29,101 +29,90 @@ tag:
|
|||||||
使用上面金矿的例子。这里我们有矮人的矿工等级制度。
|
使用上面金矿的例子。这里我们有矮人的矿工等级制度。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class DwarvenMineWorker {
|
public abstract class DwarvenMineWorker {
|
||||||
|
|
||||||
public void goToSleep() {
|
public void goToSleep() {
|
||||||
LOGGER.info("{} goes to sleep.", name());
|
LOGGER.info("{} goes to sleep.", name());
|
||||||
}
|
|
||||||
|
|
||||||
public void wakeUp() {
|
|
||||||
LOGGER.info("{} wakes up.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goHome() {
|
|
||||||
LOGGER.info("{} goes home.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goToMine() {
|
|
||||||
LOGGER.info("{} goes to the mine.", name());
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
LOGGER.info("Undefined action");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void action(Action... actions) {
|
public void wakeUp() {
|
||||||
Arrays.stream(actions).forEach(this::action);
|
LOGGER.info("{} wakes up.", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void work();
|
public void goHome() {
|
||||||
|
LOGGER.info("{} goes home.", name());
|
||||||
|
}
|
||||||
|
|
||||||
public abstract String name();
|
public void goToMine() {
|
||||||
|
LOGGER.info("{} goes to the mine.", name());
|
||||||
|
}
|
||||||
|
|
||||||
enum Action {
|
private void action(Action action) {
|
||||||
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
switch (action) {
|
||||||
}
|
case GO_TO_SLEEP -> goToSleep();
|
||||||
|
case WAKE_UP -> wakeUp();
|
||||||
|
case GO_HOME -> goHome();
|
||||||
|
case GO_TO_MINE -> goToMine();
|
||||||
|
case WORK -> work();
|
||||||
|
default -> LOGGER.info("Undefined action");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void action(Action... actions) {
|
||||||
|
Arrays.stream(actions).forEach(this::action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void work();
|
||||||
|
|
||||||
|
public abstract String name();
|
||||||
|
|
||||||
|
enum Action {
|
||||||
|
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DwarvenTunnelDigger extends DwarvenMineWorker {
|
public class DwarvenTunnelDigger extends DwarvenMineWorker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void work() {
|
public void work() {
|
||||||
LOGGER.info("{} creates another promising tunnel.", name());
|
LOGGER.info("{} creates another promising tunnel.", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return "Dwarven tunnel digger";
|
return "Dwarven tunnel digger";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DwarvenGoldDigger extends DwarvenMineWorker {
|
public class DwarvenGoldDigger extends DwarvenMineWorker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void work() {
|
public void work() {
|
||||||
LOGGER.info("{} digs for gold.", name());
|
LOGGER.info("{} digs for gold.", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return "Dwarf gold digger";
|
return "Dwarf gold digger";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DwarvenCartOperator extends DwarvenMineWorker {
|
public class DwarvenCartOperator extends DwarvenMineWorker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void work() {
|
public void work() {
|
||||||
LOGGER.info("{} moves gold chunks out of the mine.", name());
|
LOGGER.info("{} moves gold chunks out of the mine.", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return "Dwarf cart operator";
|
return "Dwarf cart operator";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
+51
-59
@@ -56,70 +56,62 @@ public interface StarMemento {
|
|||||||
|
|
||||||
public class Star {
|
public class Star {
|
||||||
|
|
||||||
private StarType type;
|
|
||||||
private int ageYears;
|
|
||||||
private int massTons;
|
|
||||||
|
|
||||||
public Star(StarType startType, int startAge, int startMass) {
|
|
||||||
this.type = startType;
|
|
||||||
this.ageYears = startAge;
|
|
||||||
this.massTons = startMass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void timePasses() {
|
|
||||||
ageYears *= 2;
|
|
||||||
massTons *= 8;
|
|
||||||
switch (type) {
|
|
||||||
case RED_GIANT:
|
|
||||||
type = StarType.WHITE_DWARF;
|
|
||||||
break;
|
|
||||||
case SUN:
|
|
||||||
type = StarType.RED_GIANT;
|
|
||||||
break;
|
|
||||||
case SUPERNOVA:
|
|
||||||
type = StarType.DEAD;
|
|
||||||
break;
|
|
||||||
case WHITE_DWARF:
|
|
||||||
type = StarType.SUPERNOVA;
|
|
||||||
break;
|
|
||||||
case DEAD:
|
|
||||||
ageYears *= 2;
|
|
||||||
massTons = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StarMemento getMemento() {
|
|
||||||
var state = new StarMementoInternal();
|
|
||||||
state.setAgeYears(ageYears);
|
|
||||||
state.setMassTons(massTons);
|
|
||||||
state.setType(type);
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMemento(StarMemento memento) {
|
|
||||||
var state = (StarMementoInternal) memento;
|
|
||||||
this.type = state.getType();
|
|
||||||
this.ageYears = state.getAgeYears();
|
|
||||||
this.massTons = state.getMassTons();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("%s age: %d years mass: %d tons", type.toString(), ageYears, massTons);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class StarMementoInternal implements StarMemento {
|
|
||||||
|
|
||||||
private StarType type;
|
private StarType type;
|
||||||
private int ageYears;
|
private int ageYears;
|
||||||
private int massTons;
|
private int massTons;
|
||||||
|
|
||||||
// setters and getters ->
|
public Star(StarType startType, int startAge, int startMass) {
|
||||||
|
this.type = startType;
|
||||||
|
this.ageYears = startAge;
|
||||||
|
this.massTons = startMass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void timePasses() {
|
||||||
|
ageYears *= 2;
|
||||||
|
massTons *= 8;
|
||||||
|
switch (type) {
|
||||||
|
case RED_GIANT -> type = StarType.WHITE_DWARF;
|
||||||
|
case SUN -> type = StarType.RED_GIANT;
|
||||||
|
case SUPERNOVA -> type = StarType.DEAD;
|
||||||
|
case WHITE_DWARF -> type = StarType.SUPERNOVA;
|
||||||
|
case DEAD -> {
|
||||||
|
ageYears *= 2;
|
||||||
|
massTons = 0;
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StarMemento getMemento() {
|
||||||
|
var state = new StarMementoInternal();
|
||||||
|
state.setAgeYears(ageYears);
|
||||||
|
state.setMassTons(massTons);
|
||||||
|
state.setType(type);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMemento(StarMemento memento) {
|
||||||
|
var state = (StarMementoInternal) memento;
|
||||||
|
this.type = state.getType();
|
||||||
|
this.ageYears = state.getAgeYears();
|
||||||
|
this.massTons = state.getMassTons();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s age: %d years mass: %d tons", type.toString(), ageYears, massTons);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StarMementoInternal implements StarMemento {
|
||||||
|
|
||||||
|
private StarType type;
|
||||||
|
private int ageYears;
|
||||||
|
private int massTons;
|
||||||
|
|
||||||
|
// setters and getters ->
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -49,24 +49,16 @@ public class Star {
|
|||||||
ageYears *= 2;
|
ageYears *= 2;
|
||||||
massTons *= 8;
|
massTons *= 8;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RED_GIANT:
|
case RED_GIANT -> type = StarType.WHITE_DWARF;
|
||||||
type = StarType.WHITE_DWARF;
|
case SUN -> type = StarType.RED_GIANT;
|
||||||
break;
|
case SUPERNOVA -> type = StarType.DEAD;
|
||||||
case SUN:
|
case WHITE_DWARF -> type = StarType.SUPERNOVA;
|
||||||
type = StarType.RED_GIANT;
|
case DEAD -> {
|
||||||
break;
|
|
||||||
case SUPERNOVA:
|
|
||||||
type = StarType.DEAD;
|
|
||||||
break;
|
|
||||||
case WHITE_DWARF:
|
|
||||||
type = StarType.SUPERNOVA;
|
|
||||||
break;
|
|
||||||
case DEAD:
|
|
||||||
ageYears *= 2;
|
ageYears *= 2;
|
||||||
massTons = 0;
|
massTons = 0;
|
||||||
break;
|
}
|
||||||
default:
|
default -> {
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-22
@@ -26,30 +26,17 @@ public final class CalculatorViewModel {
|
|||||||
*/
|
*/
|
||||||
void handleAction(final CalculatorAction action) {
|
void handleAction(final CalculatorAction action) {
|
||||||
switch (action.tag()) {
|
switch (action.tag()) {
|
||||||
case AdditionCalculatorAction.TAG:
|
case AdditionCalculatorAction.TAG -> add();
|
||||||
add();
|
case SubtractionCalculatorAction.TAG -> subtract();
|
||||||
break;
|
case MultiplicationCalculatorAction.TAG -> multiply();
|
||||||
|
case DivisionCalculatorAction.TAG -> divide();
|
||||||
case SubtractionCalculatorAction.TAG:
|
case SetVariableCalculatorAction.TAG -> {
|
||||||
subtract();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MultiplicationCalculatorAction.TAG:
|
|
||||||
multiply();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DivisionCalculatorAction.TAG:
|
|
||||||
divide();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SetVariableCalculatorAction.TAG:
|
|
||||||
SetVariableCalculatorAction setVariableAction =
|
SetVariableCalculatorAction setVariableAction =
|
||||||
(SetVariableCalculatorAction) action;
|
(SetVariableCalculatorAction) action;
|
||||||
setVariable(setVariableAction.getVariable());
|
setVariable(setVariableAction.getVariable());
|
||||||
break;
|
}
|
||||||
|
default -> {
|
||||||
default:
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,16 +45,12 @@ public class RangeShardManager extends ShardManager {
|
|||||||
@Override
|
@Override
|
||||||
protected int allocateShard(Data data) {
|
protected int allocateShard(Data data) {
|
||||||
var type = data.getType();
|
var type = data.getType();
|
||||||
switch (type) {
|
return switch (type) {
|
||||||
case TYPE_1:
|
case TYPE_1 -> 1;
|
||||||
return 1;
|
case TYPE_2 -> 2;
|
||||||
case TYPE_2:
|
case TYPE_3 -> 3;
|
||||||
return 2;
|
default -> -1;
|
||||||
case TYPE_3:
|
};
|
||||||
return 3;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user