Skip to content

Commit 9131e98

Browse files
committed
builder patterns
1 parent 1111e59 commit 9131e98

20 files changed

+188
-213
lines changed

README.md

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
11
# Design Patterns in Java
2-
- hands on exercises following one [Udemy class](https://www.udemy.com/course/design-patterns-java/) and [Design Patterns book](https://en.wikipedia.org/wiki/Design_Patterns)
3-
4-
2+
- Hands on exercises following belows
3+
- [udemy class](https://www.udemy.com/course/design-patterns-java/)
4+
- [design patterns and principles paper](https://fi.ort.edu.uy/innovaportal/file/2032/1/design_principles.pdf)
5+
- [design patterns book](https://en.wikipedia.org/wiki/Design_Patterns)
56

67
## SOLID
78

8-
### Single Responsibility Principle
9+
### [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single-responsibility_principle)
910
`There should never be more than one reason for a class to change.` i.e. every class should have only one responsibility.
1011

11-
### Open Closed Principle (OCP)
12+
### [Open Closed Principle (OCP)](https://en.wikipedia.org/wiki/Open–closed_principle)
1213
`open for extension, but closed for modification.`
1314
- OCP + [Specification Pattern](https://en.wikipedia.org/wiki/Specification_pattern)
1415

15-
### Liskov Substitution Principle
16+
### [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle)
1617
`if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.` i.e. if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.
17-
- s
18+
- Circle / Ellipse Dilemma (can be Square / Rectangle Problem)
19+
20+
### [Interface Segregation Principle](https://en.wikipedia.org/wiki/Interface_segregation_principle)
21+
`Many client-specific interfaces are better than one general-purpose interface.`
22+
23+
### [Dependency Inversion Principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle)
24+
`Depend upon abstractions, [not] concretions.`
25+
- High-level modules should not import anything from low-level modules. Both should depend on abstractions (e.g., interfaces).
26+
- Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions
27+
28+
## Creational Patterns
29+
### [Builder Pattern](https://en.wikipedia.org/wiki/Builder_pattern)
30+
- StringBuilder and HTMLBuilder
31+
32+
## Structural Patterns
33+
34+
## Behavioral Patterns
35+
36+
## Concurrency Patterns

pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
<maven.compiler.source>17</maven.compiler.source>
1313
<maven.compiler.target>17</maven.compiler.target>
1414
</properties>
15-
15+
16+
1617
</project>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package creational.builder;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
7+
public class CodeBuilder {
8+
private record Field(String name, String type) {
9+
}
10+
11+
private final String className;
12+
private final List<Field> fields = new ArrayList<>();
13+
private final int indentSize = 4;
14+
15+
16+
public CodeBuilder(String className) {
17+
this.className = className;
18+
}
19+
20+
public CodeBuilder addField(String name, String type) {
21+
fields.add(new Field(name, type));
22+
return this;
23+
}
24+
25+
public String buildCode() {
26+
final StringBuilder sb = new StringBuilder();
27+
sb.append(String.format("public class %s\n", className));
28+
sb.append("{\n");
29+
fields.forEach(field -> sb.append(String.format("%" + indentSize + "s" + "public %s %s;\n", "", field.type, field.name)));
30+
sb.append("}\n");
31+
32+
return sb.toString();
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return buildCode();
38+
}
39+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package creational.builder;
2+
3+
4+
public class Demo {
5+
6+
public static void main(String[] args) {
7+
// we want to build a simple HTML paragraph
8+
System.out.println("Testing");
9+
String hello = "hello";
10+
StringBuilder sb = new StringBuilder();
11+
sb.append("<p>")
12+
.append(hello)
13+
.append("</p>"); // a builder!
14+
System.out.println(sb);
15+
16+
// now we want to build a list with 2 words
17+
String[] words = {"hello", "world"};
18+
sb.setLength(0); // clear it
19+
sb.append("<ul>\n");
20+
for (String word : words) {
21+
// indentation management, line breaks and other evils
22+
sb.append(String.format(" <li>%s</li>\n", word));
23+
}
24+
sb.append("</ul>");
25+
System.out.println(sb);
26+
27+
// ordinary non-fluent builder
28+
HtmlBuilder builder = new HtmlBuilder("ul");
29+
builder.addChild("li", "hello");
30+
builder.addChild("li", "world");
31+
System.out.println(builder);
32+
33+
// fluent builder
34+
builder.clear();
35+
builder.addChildFluent("li", "hello")
36+
.addChildFluent("li", "world");
37+
System.out.println(builder);
38+
39+
40+
41+
// Class Builder
42+
CodeBuilder cb = new CodeBuilder("Person").addField("age", "int").addField("name", "String");
43+
System.out.println(cb);
44+
}
45+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package creational.builder;
2+
3+
public class HtmlBuilder {
4+
private String rootName;
5+
private HtmlElement root = new HtmlElement();
6+
7+
public HtmlBuilder(String rootName) {
8+
this.rootName = rootName;
9+
root.name = rootName;
10+
}
11+
12+
// not fluent
13+
public void addChild(String childName, String childText) {
14+
HtmlElement e = new HtmlElement(childName, childText);
15+
root.elements.add(e);
16+
}
17+
18+
public HtmlBuilder addChildFluent(String childName, String childText) {
19+
HtmlElement e = new HtmlElement(childName, childText);
20+
root.elements.add(e);
21+
return this;
22+
}
23+
24+
public void clear() {
25+
root = new HtmlElement();
26+
root.name = rootName;
27+
}
28+
29+
// delegating
30+
@Override
31+
public String toString() {
32+
return root.toString();
33+
}
34+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package creational.builder;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
6+
public class HtmlElement {
7+
protected int p;
8+
public String name, text;
9+
public ArrayList<HtmlElement> elements = new ArrayList<>();
10+
private final int indentSize = 2;
11+
private final String newLine = System.lineSeparator();
12+
13+
public HtmlElement() {
14+
}
15+
16+
public HtmlElement(String name, String text) {
17+
this.name = name;
18+
this.text = text;
19+
}
20+
21+
private String toStringImpl(int indent) {
22+
StringBuilder sb = new StringBuilder();
23+
String i = String.join("", Collections.nCopies(indent * indentSize, " "));
24+
sb.append(String.format("%s<%s>%s", i, name, newLine));
25+
if (text != null && !text.isEmpty()) {
26+
sb.append(String.join("", Collections.nCopies(indentSize * (indent + 1), " ")))
27+
.append(text)
28+
.append(newLine);
29+
}
30+
31+
for (HtmlElement e : elements)
32+
sb.append(e.toStringImpl(indent + 1));
33+
34+
sb.append(String.format("%s</%s>%s", i, name, newLine));
35+
return sb.toString();
36+
}
37+
38+
@Override
39+
public String toString() {
40+
return toStringImpl(0);
41+
}
42+
}

src/main/java/lsp/Demo.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/main/java/lsp/Rectangle.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/lsp/Square.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/main/java/ocp/AndSpecification.java

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)