Skip to content

Commit a35aad3

Browse files
refactored some patterns: Command, Decorator, Facade, Visitor
1 parent d78442a commit a35aad3

File tree

6 files changed

+138
-59
lines changed

6 files changed

+138
-59
lines changed

src/main/kotlin/design_patterns/Command.kt

+12-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ package design_patterns
22

33
/**
44
*
5-
* pattern: Command
6-
*
7-
* description: it's a behavioral pattern that allows you to wrap requests or simple operations in separate objects.
5+
* Command is a behavioral pattern that allows you to wrap requests or simple operations in separate objects
86
*
97
* P.S. Kotlin variant of this pattern is shown in tests
108
*
@@ -31,3 +29,14 @@ class MultiCommand(private val coefficient: Int) : ArithmeticCommand {
3129
return number * coefficient
3230
}
3331
}
32+
33+
// we can also create the command that accepts others
34+
class MacroCommand(private vararg val commands: ArithmeticCommand) : ArithmeticCommand {
35+
override fun execute(number: Int): Int {
36+
var result = number
37+
commands.forEach {
38+
result = it.execute(result)
39+
}
40+
return result
41+
}
42+
}

src/main/kotlin/design_patterns/Decorator.kt

+7-18
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ package design_patterns
22

33
/**
44
*
5-
* pattern: Decorator
5+
* Decorator is a structural design pattern that adds new functionality to an object:
66
*
7-
* using: used to add additional functionality to an object
7+
* classes implement a common interface and to extend the functionality of the previous object,
88
*
9-
* description: classes implement a common interface and to extend the functionality of the previous object,
109
* the old object is passed through the constructor
1110
*
1211
*/
@@ -15,45 +14,35 @@ interface MyPrinter {
1514
fun printedText() : String
1615
}
1716

18-
/**
19-
* just returns "Hello"
20-
*/
17+
// just returns "Hello"
2118
class HelloPrinter : MyPrinter {
2219
override fun printedText() : String {
2320
return "Hello"
2421
}
2522
}
2623

27-
/**
28-
* adds a comma to the previous value of the printedText() function
29-
*/
24+
// adds a comma to the previous value of the printedText() function
3025
class CommaPrinter(private val printer: MyPrinter) : MyPrinter {
3126
override fun printedText() : String {
3227
return "${printer.printedText()},"
3328
}
3429
}
3530

36-
/**
37-
* adds a space to the previous value of the printedText() function
38-
*/
31+
// adds a space to the previous value of the printedText() function
3932
class SpacePrinter(private val printer: MyPrinter) : MyPrinter {
4033
override fun printedText() : String {
4134
return "${printer.printedText()} "
4235
}
4336
}
4437

45-
/**
46-
* adds the word "World" to the previous value of the printedText() function
47-
*/
38+
// adds the word "World" to the previous value of the printedText() function
4839
class WorldPrinter(private val printer: MyPrinter) : MyPrinter {
4940
override fun printedText() : String {
5041
return "${printer.printedText()}World"
5142
}
5243
}
5344

54-
/**
55-
* adds an exclamation mark to the previous value of the printedText() function
56-
*/
45+
// adds an exclamation mark to the previous value of the printedText() function
5746
class ExclamationPrinter(private val printer: MyPrinter) : MyPrinter {
5847
override fun printedText() : String {
5948
return "${printer.printedText()}!"

src/main/kotlin/design_patterns/Facade.kt

+79-29
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,101 @@ package design_patterns
22

33
/**
44
*
5-
* pattern: Facade
5+
* Facade is a structural design pattern that simplifies the interface to a group of interfaces
66
*
7-
* using: used to simplify access to an object with a complex implementation
8-
*
9-
* description: a complex object contains several dependencies within itself, which it combines with each other
7+
* with a more complex implementation
108
*
119
*/
1210

11+
data class GoodsEntity(
12+
private val id: Long,
13+
private val name: String,
14+
private val description: String,
15+
private val price: Double
16+
)
1317

14-
/**
15-
* imitation of local data storage (database)
16-
*/
17-
class LocalDataSource {
18-
19-
private val data = mutableListOf<String>()
18+
class GoodsDatabase {
19+
private val cachedGoods = mutableListOf<GoodsEntity>()
2020

21-
fun save(data: List<String>) {
22-
this.data.addAll(data)
21+
fun save(goods: List<GoodsEntity>) {
22+
cachedGoods.addAll(goods)
2323
}
2424

25-
fun read() = data
26-
fun isEmpty() = data.isEmpty()
25+
fun read() = cachedGoods
26+
}
27+
28+
class GoodsNetworkService {
29+
30+
fun fetch() = listOf(
31+
GoodsEntity(
32+
id = 1,
33+
name = "Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software 2nd Edition",
34+
description = "You know you don't want to reinvent the wheel, so you look to Design Patterns: the lessons learned by those who've faced the same software design problems.",
35+
price = 41.94
36+
)
37+
)
2738

2839
}
2940

30-
/**
31-
* network request simulation
32-
*/
33-
class NetworkDataSource {
34-
fun get() = listOf(
35-
"Harry Potter",
36-
"Ronald Weasley",
37-
"Hermione Granger"
41+
data class CategoryEntity(
42+
private val id: Long,
43+
private val name: String
44+
)
45+
46+
class CategoryDatabase {
47+
private val cachedCategories = mutableListOf<CategoryEntity>()
48+
49+
fun save(goods: List<CategoryEntity>) {
50+
cachedCategories.addAll(goods)
51+
}
52+
53+
fun read() = cachedCategories
54+
}
55+
56+
class CategoryNetworkService {
57+
58+
fun fetch() = listOf(
59+
CategoryEntity(
60+
id = 1,
61+
name = "Books"
62+
)
3863
)
64+
3965
}
4066

41-
class Repository(private val localSource: LocalDataSource, private val networkSource: NetworkDataSource) {
67+
data class GoodsResult(
68+
val goods: List<GoodsEntity>,
69+
val categories: List<CategoryEntity>
70+
)
71+
72+
// we have a group of interfaces (databases and network services)
73+
class GoodsRepository(
74+
private val goodsDatabase: GoodsDatabase,
75+
private val goodsNetworkService: GoodsNetworkService,
76+
private val categoryDatabase: CategoryDatabase,
77+
private val categoryNetworkService: CategoryNetworkService
78+
) {
4279

43-
fun fetch() : List<String> {
44-
// I omitted error handling for simplicity
45-
if (localSource.isEmpty()) {
46-
val data = networkSource.get()
47-
localSource.save(data)
80+
// we need a simpler interface
81+
fun goodsAndCategories() : GoodsResult {
82+
val goods = goodsDatabase.read().toMutableList()
83+
if (goods.isEmpty()) {
84+
val networkGoods = goodsNetworkService.fetch()
85+
goodsDatabase.save(networkGoods)
86+
goods.addAll(networkGoods)
4887
}
49-
return localSource.read()
88+
89+
val categories = categoryDatabase.read().toMutableList()
90+
if (categories.isEmpty()) {
91+
val networkCategories = categoryNetworkService.fetch()
92+
categoryDatabase.save(networkCategories)
93+
categories.addAll(networkCategories)
94+
}
95+
96+
return GoodsResult(
97+
goods = goods,
98+
categories = categories
99+
)
50100
}
51101

52102
}

src/main/kotlin/design_patterns/Visitor.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ package design_patterns
22

33
/**
44
*
5-
* pattern: Visitor
5+
* Visitor is a behavioral design pattern that allows you to add a new operation
66
*
7-
* description: it's a behavioral pattern that allows you to add a new operation
87
* to an entire class hierarchy without changing the code of these classes.
98
*
109
*/

src/test/kotlin/design_patterns/CommandTest.kt

+15-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import org.junit.Assert.assertEquals
66
internal class CommandTest {
77

88
@Test
9-
fun test_1() {
9+
fun `test 1`() {
1010
val commands = listOf(
1111
AddCommand(10),
1212
AddCommand(20),
@@ -23,7 +23,7 @@ internal class CommandTest {
2323
}
2424

2525
@Test
26-
fun test_2() {
26+
fun `test 2`() {
2727
val commands = listOf(
2828
MultiCommand(2),
2929
MultiCommand(2),
@@ -42,7 +42,7 @@ internal class CommandTest {
4242
}
4343

4444
@Test
45-
fun test_3() {
45+
fun `test 3`() {
4646
val commands = listOf(
4747
AddCommand(-1),
4848
MinusCommand(1000),
@@ -58,7 +58,18 @@ internal class CommandTest {
5858
}
5959

6060
@Test
61-
fun test_kotlin_variant() {
61+
fun `test MacroCommand`() {
62+
val command = MacroCommand(
63+
MultiCommand(2),
64+
AddCommand(10),
65+
MinusCommand(100)
66+
)
67+
68+
assertEquals(-70, command.execute(10))
69+
}
70+
71+
@Test
72+
fun `test Kotlin variant`() {
6273
val commands: List<(Int) -> Int> = listOf(
6374
{ actual: Int -> actual + 49 },
6475
{ actual: Int -> actual - 20 },

src/test/kotlin/design_patterns/FacadeTest.kt

+24-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,30 @@ internal class FacadeTest {
77

88
@Test
99
fun test() {
10-
val facade = Repository(LocalDataSource(), NetworkDataSource())
11-
val data = facade.fetch()
12-
assertEquals(listOf("Harry Potter", "Ronald Weasley", "Hermione Granger"), data)
10+
val goodsRepository = GoodsRepository(
11+
GoodsDatabase(),
12+
GoodsNetworkService(),
13+
CategoryDatabase(),
14+
CategoryNetworkService()
15+
)
16+
17+
val actual = goodsRepository.goodsAndCategories()
18+
19+
assertEquals(
20+
GoodsResult(
21+
goods = listOf(GoodsEntity(
22+
id = 1,
23+
name = "Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software 2nd Edition",
24+
description = "You know you don't want to reinvent the wheel, so you look to Design Patterns: the lessons learned by those who've faced the same software design problems.",
25+
price = 41.94
26+
)),
27+
categories = listOf(CategoryEntity(
28+
id = 1,
29+
name = "Books"
30+
))
31+
),
32+
actual
33+
)
1334
}
1435

1536
}

0 commit comments

Comments
 (0)