<style>
code.orange {
color: #F7A004 !important;
}
</style>
## *Design Pattern*
# <code class="orange"><b>Decorator Pattern</b></code>
Speaker - Wendy
---
# Wiki
- Allows behavior to be added to an individual object, dynamically
- Without affecting the behavior of other objects from the same class.
---
# Real - World
---

---
### Create a Person class
```kotlin
interface Human {
fun getBody()
}
class Person : Human {
override fun getBody() {
println("Person's body")
}
}
```
---
### Wear clothes
```kotlin
class Person : Human {
override fun getBody() {
println("Person's body")
println("Wear a sweater")
println("Put on a raincoat")
}
}
```
`getBody() has too many behaviors!`
---
### Base Decorator
```kotlin
abstract class ClothingDecorator(private val human: Human) : Human {
override fun getBody() {
human.getBody()
}
}
```
---
### Add a sweater
```kotlin
class SweaterDecorator(private val human: Human) : ClothingDecorator(human) {
override fun getBody() {
super.getBody()
println("Wear a sweater")
}
}
```
---
### Wear a sweater
```kotlin
fun main() {
val person = SweaterDecorator(Person())
person.getBody()
}
```
#### Result
```
Person's body
Wear a sweater
```
---
### Add a raincoat
```kotlin
class RaincoatDecorator(private val human: Human) : ClothingDecorator(human) {
override fun getBody() {
super.getBody()
println("Wear a raincoat")
}
}
```
---
### Wear a raincoat
```kotlin
fun main() {
val person = RaincoatDecorator(SweaterDecorator(Person()))
person.getBody()
}
```
#### Result
```
Person's body
Wear a sweater
Wear a raincoat
```
---
# For App
---
## For App - Ad Banner

---
### Ads Statistics
*Ads - provided callback interface*
```kotlin
interface AdEventListener {
fun onAdScrollByUser()
fun onAdAutoScroll()
}
```
---
### Ads Statistics
*Implementation knows nothing about stats*
```kotlin
class AdBannerEventListenerImpl : AdEventListener {
override fun onAdScrollByUser() {
println("Do scrolling by user logic")
}
override fun onAdAutoScroll() {
println("Do auto scrolling logic")
}
}
```
---
### Ads Statistics
*All stats logic is encapsulated into decorator*
```kotlin
class AdEventListenerLoggingDecorator(
private val target: AdEventListener,
private val statistics: GAStatistics
) : AdEventListener by target {
override fun onAdScrollByUser() {
target.onAdScrollByUser()
statistics.sendEvent(“ad_scroll_by_user”)
}
override fun onAdAutoScroll() {
target.onAdAutoScroll()
statistics.sendEvent(“ad_auto_scroll”)
}
}
```
---
### Ads Statistics
```kotlin
fun main() {
val adBanner = AdEventListenerLoggingDecorator(
AdBannerEventListenerImpl(),
GAStatistics()
)
adBanner.onAdScrollByUser()
adBanner.onAdAutoScroll()
}
```
---
## Pros
- Extend an object’s behavior without making a new subclass.
- Add or remove responsibilities from an object at runtime.
- Combine several behaviors by wrapping an object into multiple decorators.
- Single Responsibility Principle.
---
## Cons
- Hard to implement a decorator in such a way that its behavior doesn’t depend on the order in the decorators stack.
- The initial configuration code of layers might look pretty ugly.
---
### Reference - Android
- [Java decorator example](https://refactoring.guru/design-patterns/decorator/java/example)
- [Applying decorator pattern to decorate views on Android](https://www.javacodegeeks.com/2014/08/applying-decorator-pattern-to-decorate-views-on-android.html)
- [Decorator pattern in Android](https://medium.com/@denisrebrof/decorator-pattern-in-android-development-5dd1637710fa)
- [Decorator pattern in Android development](https://www.reddit.com/r/androiddev/comments/a6p6y4/decorator_pattern_in_android_development/)
---
### Reference - iOS
- [Swift Design Patterns in Practice: the Decorator Pattern](https://stablekernel.com/article/swift-design-patterns-in-practice-the-decorator-pattern/)
- [Using Decorator Pattern to Add Architectural Non-Intrusive Analytics in Swift](https://holyswift.app/using-decorator-pattern-to-add-architectural-non-intrusive-analytics-in-swift/)
- [Design Patterns in Swift - Decorator](https://vinileal.com/design%20patterns/design-patterns-swift-decorator/)
{"metaMigratedAt":"2023-06-17T12:25:12.846Z","metaMigratedFrom":"YAML","title":"<code class=\"orange\"><b>Decorator Pattern</b></code>","breaks":true,"contributors":"[{\"id\":\"17076682-2483-46ff-99ad-cd09df8cced9\",\"add\":8082,\"del\":3459}]"}