** Table of Contents ** Normally, the part that can be extracted is an abstract class, and the other parts are implemented by a concrete class that inherits the abstract class.
This pattern separates the abstract class from the concrete class so that the implementation of the abstract class can be decided at runtime.
Take an icon class that manages information about icons as an example. First ** monochrome icon class (abstract class) ** and ** large monochrome icon class (concrete class) ** for displaying monochrome icons in various sizes **, ** medium monochrome icon class (concrete class) * *, ** Implement small monochrome icon class (concrete class) **. However, due to an unplanned specification change from the client, it became necessary to implement ** color icon class (abstract class) ** that allows RGB to be set freely on the way. Of course, the icon must meet the specifications for displaying three types, large, medium, and small, like the monochrome icon.
When the abstract class and the concrete class are permanently combined by inheritance, ** color icon class ** inherited ** large color icon class **, ** medium color icon class ** ... omitted
You will have to create all large to small icons that inherit the color icon class. When adding more clear icons, do the same ... Omitted
Is it a similar idea to create an intermediate table and normalize a table with many-to-many relations in DB?
Separate the extracted classes and implementations so that they can be modified independently.
· Abstraction abstract class -A class that extends the RefinedAbstraction Abstraction class ・ Implementor concrete class -A class that extends the ConcreteImplementor Implementor class
First, implement the monochrome icon class and color icon class of the abstract class.
Abstract icon class This class is the heart of the so-called pattern, the ** bridge ** of the abstract and concrete classes.
AbstIcon.kt
package bridge
abstract class AbstIcon(iconType: IconType) {
enum class IconType(val value: String) {
BlackAndWhite("Monochrome icon"),
Color("Color icon")
}
private var bigIcon: ImpIcon = BigIcon(iconType)
private var middleIcon: ImpIcon = MiddleIcon(iconType)
private var smallIcon: ImpIcon = SmallIcon(iconType)
abstract fun getType(): String
fun getBigIcon(): ImpIcon {
return bigIcon
}
fun getMiddleIcon(): ImpIcon {
return middleIcon
}
fun getSmallIcon(): ImpIcon {
return smallIcon
}
}
Monochrome icon abstract class
AbstBlackAndWhiteIcon.kt
package bridge
class AbstBlackAndWhiteIcon: AbstIcon(IconType.BlackAndWhite) {
override fun getType(): String {
return AbstIcon.IconType.BlackAndWhite.value
}
//Monochrome icon original processing various
}
Color icon abstract class
AbstColorIcon.kt
package bridge
class AbstColorIcon: AbstIcon(IconType.Color) {
override fun getType(): String {
return AbstIcon.IconType.Color.value
}
//Various color icon original processing
}
Next, create concrete classes such as large icons, medium icons, and small icons.
Concrete icon interface
ImpIcon.kt
package bridge
interface ImpIcon {
enum class IconSize(val value: String) {
Big("Large icon"),
Middle("Medium icon"),
Small("Small icon")
}
fun getIcon(): String
}
Large, medium and small icon classes
BigIcon.kt
package bridge
class BigIcon(iconType: AbstIcon.IconType): ImpIcon {
private val iconType = iconType
override fun getIcon(): String {
return "【type】:" + iconType.value + "【size】:" + ImpIcon.IconSize.Big.value
}
}
MiddleIcon.kt
package bridge
class MiddleIcon(iconType: AbstIcon.IconType): ImpIcon {
private val iconType = iconType
override fun getIcon(): String {
return "【type】:" + iconType.value + "【size】:" + ImpIcon.IconSize.Middle.value
}
}
SmallIcon.kt
package bridge
class SmallIcon(iconType: AbstIcon.IconType): ImpIcon {
private val iconType = iconType
override fun getIcon(): String {
return "【type】:" + iconType.value + "【size】:" + ImpIcon.IconSize.Small.value
}
}
Client.kt
package bridge
class Client {
init {
val colorIcon = AbstColorIcon()
println(colorIcon.getType())
println(colorIcon.getBigIcon().getIcon())
println(colorIcon.getMiddleIcon().getIcon())
println(colorIcon.getSmallIcon().getIcon())
val blackAndWhiteIcon = AbstBlackAndWhiteIcon()
println(blackAndWhiteIcon.getType())
println(blackAndWhiteIcon.getBigIcon().getIcon())
println(blackAndWhiteIcon.getMiddleIcon().getIcon())
println(blackAndWhiteIcon.getSmallIcon().getIcon())
}
}
This completes the implementation of the sample code using the icon.
[output]
Color icon
[Type]: Color icon [Size]: Large icon
[Type]: Color icon [Size]: Medium icon
[Type]: Color icon [Size]: Small icon
Monochrome icon
[Type]: Monochrome icon [Size]: Large icon
[Type]: Monochrome icon [Size]: Medium icon
[Type]: Monochrome icon [Size]: Small icon
Now let's add a clear icon with a transparent background. In the conventional method, ** large clear eye ** ... is abbreviated, but in this pattern, it can be realized only by implementing AbstClearIcon class` `` which inherits
AbstIcon class` ``. ..
AbstClearIcon.kt
package bridge
class AbstClearIcon: AbstIcon(IconType.Clear) {
override fun getType(): String {
return AbstIcon.IconType.Clear.value
}
//Clear icon original processing various
}
Add the following code to the Client class and try again.
Client.kt
val clearIcon = AbstClearIcon()
println(clearIcon.getType())
println(clearIcon.getBigIcon().getIcon())
println(clearIcon.getMiddleIcon().getIcon())
println(clearIcon.getSmallIcon().getIcon())
[output]
Color icon
[Type]: Color icon [Size]: Large icon
[Type]: Color icon [Size]: Medium icon
[Type]: Color icon [Size]: Small icon
Monochrome icon
[Type]: Monochrome icon [Size]: Large icon
[Type]: Monochrome icon [Size]: Medium icon
[Type]: Monochrome icon [Size]: Small icon
Clear icon
[Type]: Clear icon [Size]: Large icon
[Type]: Clear icon [Size]: Medium icon
[Type]: Clear icon [Size]: Small icon
It was easy to expand.
This makes it possible to easily implement it no matter how much the abstract class side increases or the concrete class side increases.
Recommended Posts