로버트 마틴이 2000년대 초에 명명한 객체 지향 프로그래밍의 다섯 가지 기본 원칙을 마이클 페더스가 원칙의 앞 글자를 따서 다시 SOLID라는 이름으로 소개한 것.
class Order {
fun sendOrderUpdateNotification() {
// sends notification about order updates to the user.
}
fun generateInvoice() {
// generates invoice
}
fun save() {
// insert/update data in the db
}
}
data class Order(
val id: Long,
val name: String,
// ... other properties.
)
class OrderNotificationSender {
fun sendNotification(order: Order) {
// send order notifications
}
class OrderRepository {
fun save(order: Order) {
// insert/update data in the db.
}
}
class OrderFacade(
private val orderNotificationSender: OrderNotificationSender,
private val orderInvoiceGenerator: OrderInvoiceGenerator,
private val orderRepository: OrderRepository
) {
fun sendNotification(order: Order) {
// sends notification about order updates to the user.
orderNotificationSender.sendNotification(order)
}
fun generateInvoice(order: Order) {
// generates invoice
orderInvoiceGenerator.generateInvoice(order)
}
fun save(order: Order) {
// insert/update data in the db
orderRepository.save(order)
}
}
enum class Notification {
PUSH_NOTIFICATION, EMAIL
}
class NotificationService {
fun sendNotification(notification: Notification) {
when (notification) {
Notification.PUSH_NOTIFICATION -> {
// send push notification
}
Notification.EMAIL -> {
// send email notification
}
}
}
}
enum class Notification {
PUSH_NOTIFICATION, EMAIL, SMS
}
class NotificationService {
fun sendNotification(notification: Notification) {
when (notification) {
Notification.PUSH_NOTIFICATION -> {
// send push notification
}
Notification.EMAIL -> {
// send email notification
}
Notification.SMS -> {
// send sms notification
}
}
}
}
interface Notification {
fun sendNotification()
}
class PushNotification : Notification {
override fun sendNotification() {
// send push notification
}
}
class EmailNotification : Notification {
override fun sendNotification() {
// send email notification
}
}
class NotificationService {
fun sendNotification(notification: Notification) {
notification.sendNotification()
}
}
class SMSNotification : Notification {
override fun sendNotification() {
// send sms notification
}
}
public class Rectangle {
private int height;
private int width;
public void setHeight(int height) {
this.height = height;
}
public void setWidth(int width) {
this.width = width;
}
public int area() {
return height * width;
}
}
public class Square extends Rectangle {
@Override
public void setHeight(int height) {
setSide(height);
}
@Override
public void setWidth(int width) {
setSide(width);
}
private void setSide(int side) {
super.setHeight(side);
super.setWidth(side);
}
}
fun main() {
val rectangle = Rectangle()
rectangle.setHeight(5)
rectangle.setWidth(2)
val rectangleCheck = rectangle.area() == 10 // true
val square: Rectangle = Square()
square.setHeight(5) // width is also set to 5
square.setWidth(2) // height is also set to 2
val squareCheck = square.area() == 10 // 4 false - not substitutable
}
interface Waste {
fun process()
}
class OrganicWaste : Waste {
override fun process() {
println("Processing Organic Waste")
}
}
class PlasticWaste : Waste {
override fun process() {
println("Processing Plastic Waste")
}
}
-그리고 Waste를 구현한 OrganicWaste, PlasticWaste 클래스를 만들었다.
class WasteManagementService {
fun processWaste(waste: Waste) {
waste.process()
}
}
fun main() {
val wasteManagementService = WasteManagementService()
var waste: Waste
waste = OrganicWaste()
wasteManagementService.processWaste(waste) // Output: Processing Organic Waste
waste = PlasticWaste()
wasteManagementService.processWaste(waste) // Output: Processing Plastic Waste
}
interface OnClickListener {
fun onClick()
fun onLongClick()
}
class CustomUIComponent : OnClickListener {
override fun onClick() {
// handles onClick event.
}
// left empty as I don't want the [CustomUIComponent] to have long-click behavior.
override fun onLongClick() {
}
}
interface OnLongClickListener {
fun onLongClick()
}
interface OnClickListener {
fun onClick()
}
class CustomUIComponent : OnClickListener {
override fun onClick() {
// handle single-click event
}
}
class ClassA {
fun doSomething() {
println("Doing something")
}
}
class ClassB {
fun doIt() {
val classA = ClassA() // ClassB가 제대로 작동하려면 ClassA의 인스턴스가 필요하다.
classA.doSomething()
}
}
class EmailNotification {
fun sendNotification(message: String) {
println("Sending email notification with message \"$message\"")
}
}
class NotificationService {
fun sendNotification(message: String) {
val emailNotification = EmailNotification() // <- here is the dependency
emailNotification.sendNotification(message)
}
}
fun main() {
val notificationService = NotificationService()
notificationService.sendNotification("Happy Coding") // Output: Sending email notification with message "Happy Coding"
}
interface Notification {
fun sendNotification(message: String)
}
class EmailNotification : Notification {
override fun sendNotification(message: String) {
println("Sending email notification with message \"$message\"")
}
}
class SmsNotification : Notification {
override fun sendNotification(message: String) {
println("Sending sms notification with message \"$message\"")
}
}
class NotificationService {
// this can be injected through constructor as well and it would be constructor injection
lateinit var notification: Notification
fun sendNotification(message: String) {
notification.sendNotification(message)
}
}
fun main() {
val message = "Happy Coding"
val notificationService = NotificationService()
var notification: Notification
notification = EmailNotification()
notificationService.notification = notification
notificationService.sendNotification(message)
// Output: Sending email notification with message "Happy Coding"
notification = SmsNotification()
notificationService.notification = notification
notificationService.sendNotification(message)
// Output: Sending sms notification with message "Happy Coding"
}