Skip to content

Commit c3c6e28

Browse files
committed
adds patterns docs
1 parent 7cf4037 commit c3c6e28

File tree

5 files changed

+569
-6
lines changed

5 files changed

+569
-6
lines changed

.vitepress/sidebars/java.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,17 @@ export const java = [
8282
{ text: 'Private members', link: '/java/private-members' },
8383
{ text: 'Static members', link: '/java/static-members' },
8484
{ text: 'Inheritance', link: '/java/inheritance' },
85-
{ text: 'Interfaces', link: '/java/interfaces' }
86-
// {
87-
// text: 'Design patterns',
88-
// collapsed: true,
89-
// items: [{ text: 'qq', link: '/java/qq' }]
90-
// }
85+
{ text: 'Interfaces', link: '/java/interfaces' },
86+
{
87+
text: 'Design patterns',
88+
collapsed: true,
89+
items: [
90+
{ text: 'Singleton pattern', link: '/java/singleton-pattern' },
91+
{ text: 'Adapter pattern', link: '/java/adapter-pattern' },
92+
{ text: 'Facade pattern', link: '/java/facade-pattern' },
93+
{ text: 'Mediator pattern', link: '/java/mediator-pattern' }
94+
]
95+
}
9196
]
9297
},
9398

src/java/adapter-pattern.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# The adapter pattern
2+
3+
## Purpose
4+
5+
The adapter pattern allows us to create a new interface around an existing
6+
class. This is useful when a class has the behaviours we need, but they're
7+
implemented in a way that isn't compatible with the rest of our software.
8+
9+
For example, we might have legacy code for older smart lights:
10+
11+
```js
12+
public class OldLight {
13+
public int power;
14+
15+
public OldLight() {
16+
this.power = 1;
17+
}
18+
19+
public void on() {
20+
this.power = 1;
21+
}
22+
23+
public void off() {
24+
this.power = 0;
25+
}
26+
}
27+
```
28+
29+
Using the adapter pattern, we can wrap this old code in an adapter so that we
30+
expose an `isOn` property and a `togglePower()` method, bringing it in line with
31+
the newer `SmartLight` interface.
32+
33+
## Implementation
34+
35+
First, let's define a common `Light` interface that the rest of our application
36+
will use:
37+
38+
```java
39+
public interface Light {
40+
boolean isOn();
41+
void togglePower();
42+
}
43+
```
44+
45+
Next, we'll implement the `LightAdapter` class, which adapts an instance of
46+
`OldLight` to the `Light` interface:
47+
48+
```java
49+
public class LightAdapter implements Light {
50+
private OldLight oldLight;
51+
52+
public LightAdapter(OldLight oldLight) {
53+
oldLight.off(); // Make sure it's off by default
54+
this.oldLight = oldLight;
55+
}
56+
57+
@Override
58+
public boolean isOn() {
59+
return oldLight.power == 1;
60+
}
61+
62+
@Override
63+
public void togglePower() {
64+
if (isOn()) {
65+
oldLight.off();
66+
} else {
67+
oldLight.on();
68+
}
69+
}
70+
}
71+
```
72+
73+
## Usage
74+
75+
Now, we can use the `LightAdapter` to interact with `OldLight` instances through
76+
the `Light` interface:
77+
78+
```js
79+
public class Main {
80+
public static void main(String[] args) {
81+
OldLight oldLight = new OldLight();
82+
Light adaptedLight = new LightAdapter(oldLight);
83+
84+
System.out.println(adaptedLight.isOn()); // false
85+
adaptedLight.togglePower();
86+
System.out.println(adaptedLight.isOn()); // true
87+
}
88+
}
89+
```
90+
91+
## SmartLight class
92+
93+
To show how the `Light` interface can be implemented by new classes, here's a
94+
`SmartLight` class:
95+
96+
```java
97+
public class SmartLight implements Light {
98+
private boolean power;
99+
100+
public SmartLight() {
101+
this.power = false;
102+
}
103+
104+
@Override
105+
public boolean isOn() {
106+
return power;
107+
}
108+
109+
@Override
110+
public void togglePower() {
111+
power = !power;
112+
}
113+
}
114+
```
115+
116+
Now, both `LightAdapter` (adapting `OldLight`) and `SmartLight` can be used
117+
interchangeably:
118+
119+
```java
120+
public class Main {
121+
public static void main(String[] args) {
122+
Light smartLight = new SmartLight();
123+
LightAdapter adaptedLight = new LightAdapter(new OldLight());
124+
125+
// Using SmartLight
126+
System.out.println(smartLight.isOn()); // false
127+
smartLight.togglePower();
128+
System.out.println(smartLight.isOn()); // true
129+
130+
// Using Adapted OldLight
131+
System.out.println(adaptedLight.isOn()); // false
132+
adaptedLight.togglePower();
133+
System.out.println(adaptedLight.isOn()); // true
134+
}
135+
}
136+
```

src/java/facade-pattern.md

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# The facade pattern
2+
3+
## Purpose
4+
5+
The facade pattern allows us to create a simple interface around complex
6+
operations. The facade might provide less granular control of the underlying
7+
system, but in return it can be much faster and simpler to work with.
8+
9+
Suppose we have a smart home with lots of devices, and we want a simple way of
10+
activating "holiday mode". There are a few things we need to do with our
11+
different devices which would be tedious for the users to do one by one. We can
12+
solve this by adding a facade - which in this case is a single `.holidayMode()`
13+
method.
14+
15+
## Implementation
16+
17+
Suppose our `SmartHome` class keeps track of various devices such as cameras,
18+
lights, and thermostats. Each device type has specific behaviors.
19+
20+
::: code-group
21+
22+
```java [SmartDevice.java]
23+
public abstract class SmartDevice {
24+
protected String type;
25+
26+
public String getType() {
27+
return type;
28+
}
29+
}
30+
```
31+
32+
```java [SmartCamera.java]
33+
public class SmartCamera extends SmartDevice {
34+
private boolean isOn;
35+
36+
public SmartCamera() {
37+
this.type = "camera";
38+
this.isOn = false; // Off by default
39+
}
40+
41+
public boolean isOn() {
42+
return isOn;
43+
}
44+
45+
public void togglePower() {
46+
isOn = !isOn;
47+
}
48+
}
49+
```
50+
51+
```java [SmartLight.java]
52+
public class SmartLight extends SmartDevice {
53+
private boolean isOn;
54+
55+
public SmartLight() {
56+
this.type = "light";
57+
this.isOn = false; // Off by default
58+
}
59+
60+
public boolean isOn() {
61+
return isOn;
62+
}
63+
64+
public void togglePower() {
65+
isOn = !isOn;
66+
}
67+
}
68+
```
69+
70+
```java
71+
public class SmartThermostat extends SmartDevice {
72+
private int temperature;
73+
74+
public SmartThermostat() {
75+
this.type = "thermostat";
76+
this.temperature = 20; // Default temperature
77+
}
78+
79+
public void setTemperature(int temp) {
80+
this.temperature = temp;
81+
}
82+
83+
public int getTemperature() {
84+
return temperature;
85+
}
86+
}
87+
```
88+
89+
:::
90+
91+
For "holiday mode", we want
92+
93+
- all cameras to be on
94+
- all lights to be off
95+
- all thermostats set to 5
96+
97+
We can create a facade within the `SmartHome` class to help with this.
98+
99+
```java
100+
import java.util.ArrayList;
101+
import java.util.List;
102+
import java.util.stream.Collectors;
103+
104+
public class SmartHome {
105+
private List<SmartDevice> devices;
106+
107+
public SmartHome() {
108+
devices = new ArrayList<>();
109+
}
110+
111+
// Method to add devices to the SmartHome
112+
public void addDevice(SmartDevice device) {
113+
devices.add(device);
114+
}
115+
116+
// Facade method to activate holiday mode
117+
public void holidayMode() {
118+
// Turn on all cameras
119+
for (SmartDevice device : getDevicesByType("camera")) {
120+
if (device instanceof SmartCamera) {
121+
SmartCamera camera = (SmartCamera) device;
122+
if (!camera.isOn()) {
123+
camera.togglePower();
124+
}
125+
}
126+
}
127+
128+
// Turn off all lights
129+
for (SmartDevice device : getDevicesByType("light")) {
130+
if (device instanceof SmartLight) {
131+
SmartLight light = (SmartLight) device;
132+
if (light.isOn()) {
133+
light.togglePower();
134+
}
135+
}
136+
}
137+
138+
// Set all thermostats to 5 degrees
139+
for (SmartDevice device : getDevicesByType("thermostat")) {
140+
if (device instanceof SmartThermostat) {
141+
SmartThermostat thermostat = (SmartThermostat) device;
142+
thermostat.setTemperature(5);
143+
}
144+
}
145+
}
146+
147+
// Helper method to retrieve devices by type
148+
private List<SmartDevice> getDevicesByType(String type) {
149+
return devices.stream()
150+
.filter(device -> device.getType().equals(type))
151+
.collect(Collectors.toList());
152+
}
153+
}
154+
```
155+
156+
## Usage
157+
158+
Now, instead of having our users go and configure all of these settings
159+
themselves, we can show them a button which calls holiday mode:
160+
161+
::: code-group
162+
163+
```java
164+
public class Main {
165+
public static void main(String[] args) {
166+
SmartHome smartHome = new SmartHome();
167+
168+
// Creating devices
169+
SmartCamera camera1 = new SmartCamera();
170+
SmartCamera camera2 = new SmartCamera();
171+
SmartLight light1 = new SmartLight();
172+
SmartLight light2 = new SmartLight();
173+
SmartThermostat thermostat1 = new SmartThermostat();
174+
SmartThermostat thermostat2 = new SmartThermostat();
175+
176+
// Adding devices to the smart home
177+
smartHome.addDevice(camera1);
178+
smartHome.addDevice(camera2);
179+
smartHome.addDevice(light1);
180+
smartHome.addDevice(light2);
181+
smartHome.addDevice(thermostat1);
182+
smartHome.addDevice(thermostat2);
183+
184+
// Simulating device states before holiday mode
185+
light1.togglePower(); // Turn on light1
186+
thermostat1.setTemperature(22); // Set thermostat1 to 22 degrees
187+
188+
// Activating holiday mode
189+
smartHome.holidayMode();
190+
191+
// Checking the state of devices after holiday mode
192+
System.out.println("Camera1 is on: " + camera1.isOn());
193+
System.out.println("Camera2 is on: " + camera2.isOn());
194+
System.out.println("Light1 is on: " + light1.isOn());
195+
System.out.println("Light2 is on: " + light2.isOn());
196+
System.out.println("Thermostat1 temperature: " + thermostat1.getTemperature());
197+
System.out.println("Thermostat2 temperature: " + thermostat2.getTemperature());
198+
}
199+
}
200+
```
201+
202+
```conole [output]
203+
Camera1 is on: true
204+
Camera2 is on: true
205+
Light1 is on: false
206+
Light2 is on: false
207+
Thermostat1 temperature: 5
208+
Thermostat2 temperature: 5
209+
```
210+
211+
:::
212+
213+
The user has less overall control, but a much more convenient interface.

0 commit comments

Comments
 (0)