Skip to content

Commit 3a665b9

Browse files
committed
added bloC design pattern
1 parent b375919 commit 3a665b9

File tree

11 files changed

+246
-0
lines changed

11 files changed

+246
-0
lines changed

bloC/Readme.md

Whitespace-only changes.

bloC/etc/bloC.png

65.5 KB
Loading

bloC/etc/bloC.puml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
@startuml
2+
package com.iluwatar.bloc {
3+
4+
class State {
5+
- value : int
6+
+ State(value : int)
7+
+ getValue() : int
8+
}
9+
10+
interface StateListener<T> {
11+
+ onStateChange(state : T)
12+
}
13+
14+
interface ListenerManager<T> {
15+
+ addListener(listener : StateListener<T>)
16+
+ removeListener(listener : StateListener<T>)
17+
+ getListeners() : List<StateListener<T>>
18+
}
19+
20+
class BloC {
21+
- currentState : State
22+
- listeners : List<StateListener<State>>
23+
+ BloC()
24+
+ addListener(listener : StateListener<State>)
25+
+ removeListener(listener : StateListener<State>)
26+
+ getListeners() : List<StateListener<State>>
27+
- emitState(newState : State)
28+
+ increment()
29+
+ decrement()
30+
}
31+
32+
class Main {
33+
+ main(args : String[])
34+
}
35+
36+
ListenerManager <|.. BloC
37+
StateListener <|.. BloC
38+
BloC o-- State
39+
BloC *-- StateListener
40+
}
41+
@enduml

bloC/pom.xml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.iluwatar</groupId>
8+
<artifactId>java-design-patterns</artifactId>
9+
<version>1.26.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>bloC</artifactId>
13+
14+
<properties>
15+
<maven.compiler.source>17</maven.compiler.source>
16+
<maven.compiler.target>17</maven.compiler.target>
17+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18+
</properties>
19+
<dependencies>
20+
<dependency>
21+
<groupId>org.junit.jupiter</groupId>
22+
<artifactId>junit-jupiter-api</artifactId>
23+
<scope>test</scope>
24+
</dependency>
25+
</dependencies>
26+
27+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.iluwatar.bloc;
2+
import java.util.ArrayList;
3+
import java.util.Collections;
4+
import java.util.List;
5+
6+
public class Bloc implements ListenerManager<State> {
7+
private State currentState;
8+
private final List<StateListener<State>> listeners = new ArrayList<>();
9+
10+
public Bloc() {
11+
this.currentState = new State(0);
12+
}
13+
14+
@Override
15+
public void addListener(StateListener<State> listener) {
16+
listeners.add(listener);
17+
listener.onStateChange(currentState);
18+
}
19+
20+
@Override
21+
public void removeListener(StateListener<State> listener) {
22+
listeners.remove(listener);
23+
}
24+
25+
@Override
26+
public List<StateListener<State>> getListeners() {
27+
return Collections.unmodifiableList(listeners);
28+
}
29+
30+
private void emitState(State newState) {
31+
currentState = newState;
32+
for (StateListener<State> listener : listeners) {
33+
listener.onStateChange(currentState);
34+
}
35+
}
36+
37+
public void increment() {
38+
emitState(new State(currentState.getValue() + 1));
39+
}
40+
41+
public void decrement() {
42+
emitState(new State(currentState.getValue() - 1));
43+
}
44+
}
45+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.iluwatar.bloc;
2+
import java.util.List;
3+
4+
public interface ListenerManager<T> {
5+
void addListener(StateListener<T> listener);
6+
void removeListener(StateListener<T> listener);
7+
List<StateListener<T>> getListeners();
8+
}
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.iluwatar.bloc;
2+
import javax.swing.*;
3+
import java.awt.*;
4+
5+
public class Main
6+
{
7+
public static void main(String[] args)
8+
{
9+
Bloc bloC = new Bloc();
10+
JFrame frame = new JFrame("BloC example");
11+
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
12+
frame.setSize(400, 300);
13+
JLabel counterLabel = new JLabel("Counter: 0", SwingConstants.CENTER);
14+
counterLabel.setFont(new Font("Arial", Font.BOLD, 20));
15+
JButton incrementButton = new JButton("Increment");
16+
JButton decrementButton = new JButton("Decrement");
17+
JButton toggleListenerButton = new JButton("Disable Listener");
18+
frame.setLayout(new BorderLayout());
19+
frame.add(counterLabel, BorderLayout.CENTER);
20+
frame.add(incrementButton, BorderLayout.NORTH);
21+
frame.add(decrementButton, BorderLayout.SOUTH);
22+
frame.add(toggleListenerButton, BorderLayout.EAST);
23+
24+
StateListener<State> stateListener = state -> counterLabel.setText("Counter: " + state.getValue());
25+
26+
bloC.addListener(stateListener);
27+
28+
toggleListenerButton.addActionListener(e ->
29+
{
30+
if (bloC.getListeners().contains(stateListener))
31+
{
32+
bloC.removeListener(stateListener);
33+
toggleListenerButton.setText("Enable Listener");
34+
} else
35+
{
36+
bloC.addListener(stateListener);
37+
toggleListenerButton.setText("Disable Listener");
38+
}
39+
}
40+
);
41+
incrementButton.addActionListener(e -> bloC.increment());
42+
decrementButton.addActionListener(e -> bloC.decrement());
43+
frame.setVisible(true);
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.iluwatar.bloc;
2+
3+
public class State
4+
{
5+
private final int value;
6+
7+
public State(int value)
8+
{
9+
this.value = value;
10+
}
11+
public int getValue()
12+
{
13+
return value;
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.iluwatar.bloc;
2+
3+
public interface StateListener<T>
4+
{
5+
void onStateChange(T state);
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.iluwatar.bloc;
2+
import org.junit.jupiter.api.BeforeEach;
3+
import org.junit.jupiter.api.Test;
4+
import java.util.concurrent.atomic.AtomicInteger;
5+
import static org.junit.jupiter.api.Assertions.*;
6+
7+
class BlocTest {
8+
private Bloc bloc;
9+
private AtomicInteger stateValue;
10+
@BeforeEach
11+
void setUp() {
12+
bloc = new Bloc();
13+
stateValue = new AtomicInteger(0);
14+
}
15+
@Test
16+
void initialState() {
17+
assertTrue(bloc.getListeners().isEmpty(), "No listeners should be present initially.");
18+
}
19+
20+
@Test
21+
void IncrementUpdateState() {
22+
bloc.addListener(state -> stateValue.set(state.getValue()));
23+
bloc.increment();
24+
assertEquals(1, stateValue.get(), "State should increment to 1");
25+
}
26+
27+
@Test
28+
void DecrementUpdateState() {
29+
bloc.addListener(state -> stateValue.set(state.getValue()));
30+
bloc.decrement();
31+
assertEquals(-1, stateValue.get(), "State should decrement to -1");
32+
}
33+
34+
@Test
35+
void addingListener() {
36+
bloc.addListener(state -> {});
37+
assertEquals(1, bloc.getListeners().size(), "Listener count should be 1.");
38+
}
39+
40+
@Test
41+
void removingListener() {
42+
StateListener<State> listener = state -> {};
43+
bloc.addListener(listener);
44+
bloc.removeListener(listener);
45+
assertTrue(bloc.getListeners().isEmpty(), "Listener count should be 0 after removal.");
46+
}
47+
@Test
48+
void multipleListeners() {
49+
AtomicInteger secondValue = new AtomicInteger();
50+
bloc.addListener(state -> stateValue.set(state.getValue()));
51+
bloc.addListener(state -> secondValue.set(state.getValue()));
52+
bloc.increment();
53+
assertEquals(1, stateValue.get(), "First listener should receive state 1.");
54+
assertEquals(1, secondValue.get(), "Second listener should receive state 1.");
55+
}
56+
}

pom.xml

+2
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@
218218
<module>function-composition</module>
219219
<module>microservices-distributed-tracing</module>
220220
<module>microservices-idempotent-consumer</module>
221+
<module>bloC</module>
222+
221223
</modules>
222224
<repositories>
223225
<repository>

0 commit comments

Comments
 (0)