1- اصل single responsibility (مسئولیت واحد)

اصل single responsibility بیان می کند که هر class باید تنها یک مسئولیت داشته باشد.

 data class User( var id:Long, var name:String, var password:String ){ Fun signIn(){      //this method will do signing in operation } Fun signOut(){      // this method will do signing out operation } } } 
 data class User( var id:Long, var name:String, var password:String ) Class AuthentivationService(){ Fun signIn(){  //this method will do signing in operation } Fun signOut(){ // this method will do signing out operation } } 

اگر

حالا فرض کنیم که ما باید در متدهای sign-in و sign-out ، فرایند authentication تعدادی تغییر ایجاد کنیم (شکل 1) ، در این صورت کلاس user ما تحت تأثیر قرار می گیرد.

آنگاه

برای حل مسئله باید کلاس جدیدی (شکل 2) ایجاد کنیم تا فرآیند authentication را مدیریت کرده و متدهای sign-in و sign-out را در آن کلاس move کنیم.

2- اصل open-closed

open: این بدان معناست که ما می توانیم feature های جدیدی را به کلاس های خود اضافه کنیم.

closed: این بدان معناست که feature های اصلی کلاس نباید تغییر کند.

 class Rectangle{ 	private var length 	private var height 	//getters / setters  … } class Circle{ 	private var radius  	//getters / setters  … }  class AreaFactory{ 	public fun calculateArea(shapes:ArrayList<Object>):Double{ 	var area = 0 	for (shape in shapes){ 		if(shape is Rectangle) { 		var rect = shape as Rectangle 		area += (rect.getLength()*rect.getHeight()) } else if (shape is Circle){ 	var circle = shape as Circle 	area += (circle.getRadius()*circle. getRadius ()*Math.PI) } else{ 	throw new RunTimeExeption(“shape not supported”)	 } } return area } } 
 Public interface Shape { 	fun getArea() } class Rectangle : Shape { 	private var length 	private var height 	//getters / setters  … override  fun getArea():Double { return (length*height) } class Circle: Shape { 	private var radius  	//getters / setters  … override  fun getArea():Double{ return (radius * radius *Math.PI) } class AreaFactory{ 	fun calculateArea(shapes:ArrayList<String>):Double{ 	var area:Double = 0.toDouble() 	for (shape in shapes){ 		area += shape.getArea() } return area } 	      } 

اگر

در شکل 1 می بینیم که یک دستور if else برای جدا کردن shape ها داریم ، و با افزایش shape ها ، آنها نیز به همان ترتیب به رشد خود ادامه می دهند ، زیرا کلاس برای modification (اصلاح) بسته نشده است ، یا برای extention (گسترش) نیز باز نیست.

آنگاه

ما با کمک interface این مشکل را برطرف می کنیم. در صورت نیاز به افزودن shape های بیشتر ، کلاس area factory به هیچ تغییری نیاز ندارد زیرا این کلاس از طریق اینترفیس shape ، برای توسعه باز است.

3- اصل جایگزینی liskov

کلاس فرزند (child) باید جایگزین کلاس پدر (parent) شود.

 abstract class Vehicle { protected var isEngineWorking = false abstract fun startEngine() abstract fun stopEngine() abstract fun moveForward() abstract fun moveBack() } class Car:Vehicle() {  override fun startEngine() { println("Engine started")  isEngineWorking = true } override fun stopEngine() { println("Engine stopped")  isFngineWorking = false } override fun moveForward() { println("Moving forward") } override fun moveBack() { println("Moving back!") } } class Bicycle:Vehicle(){ override fun startEngine() { TODO("Not yet implemented") } override fun stopEngine() { TODO("Not yet implemented") } override fun moveForward() { println("Moving forward") } override fun moveBack() { println("Moving back!") } } 
 interface Vehicle { fun move forward()  fun moveBack } abstract class VehicleWithEngine:Vehicle { private var isEngineWorking = false  open fun startEngine(){isEngineWorking = true}  open fun stopEngine(){isEngineWorking = false) } class Car:VehicleWithEngine(){  override fun startEngine() { super.startEngine()  println("Engine started") } override fun stopEngine() { super.stopEngine()  println("Engine stopped") } override fun moveForward() { println("Moving forward") } override fun moveBack() { println("Moving back!") } }  class Bicycle:Vehicle{  override fun moveForward() { println("Moving forward") } override fun moveBack() {  println("Moving back!") } } 

اگر

در شکل 1 هنگام ایجاد کلاس دوچرخه ، متدهای startEngine و stopEngine بی فایده خواهند بود زیرا دوچرخه موتور ندارد.

آنگاه

برای رفع این حالت ، ما می توانیم یک کلاس فرزند (child) جدید ایجاد کنیم (شکل 2) که از Vehicle ، extend می شود. این کلاس دارای موتور خواهد بود

4- اصل Interface segregation (تفکیک Interface)

این اصل بیان می کند که آن دسته از interface هایی که بسیار شلوغ و بزرگ(دارای متدهای اضافه) هستند ، باید به interface های کوچکتر تقسیم شود.

 interface Animal { fun eat()  fun sleep()  fun fly() } class Cat : Animal {  override fun eat() { println("Cat is eating fish") } override fun sleep() { println("Cat is sleeping on its owner's bed") } override fun fly() { TODO ( "Not yet implemented")   //cat can not fly!! } } class Bird : Animal { override fun eat() { println("Bird is eating forage") } override fun sleep() { println("Bird is sleeping in the nest") } override fun fly(){ println("Bird is flying in so high" } }	 
 interface Animal { fun eat() fun sleep() } interface FlyingAnimal { fun fly() } class Cat : Animal {  override fun eat() { println("Cat is eating fish") } override fun sleep() {  println("Cat is sleeping on its owner's bed") } } class Bird : Animal, FlyingAnimal { override fun eat() {   println("Bird is eating forage") } override fun sleep() { println("Bird is sleeping in the nest") } override fun fly() { println("Bird is flying in so high") } 

اگر

همانطور که در شکل 1 مشاهده می کنید برخی از حیوانات مانند گربه ها نمی توانند پرواز کنند . در حالی که implement و اجرای متد fly در آن ضروری است.

آنگاه

برای رفع این مشکل ، یک interface جدید (شکل 2) برای حیوانات پرنده ایجاد می کنیم و متد fly را از اینترفیس animalحذف می کنیم

5- اصل Dependency Inversion (وارونگی وابستگی)

این اصل بیان می کند که ماژول های سطح بالا نباید به ماژول های سطح پایین وابسته باشند.

 class AndroidDeveloper {  fun developerMobileApp(){ println("developing Android Application by using kotlin") } } class IosDeveloper {  fun developerMobileApp(){ println("developing iOS Application by using swift") } } fun main(){ val androidDeveloper = AndroidDeveloper()  val iosDeveloper = IosDeveloper()  androidDeveloper.developerMobileApp() iosDeveloper.developerMobileApp() } 
 interface MobileDeveloper{ fun developerMobileApp()  } class AndroidDeveloper (var mobileService: MobileServices): MobileDeveloper {     override fun developerMobileApp(){  println("developing Android Application by using kotlin." + "application will work with ${mobileService.serviceName}")  } enum class MobileServices (var serviceName: String) { HMS( serviceName: "Huawei Mobile Service"), GMSC serviceName: "Google Mobile Service"), BOTH( ServiceName: "Huawei Mobile Service and Google Mobile Service") } } class IosDeveloper : MobileDeveloper { override fun developerMobileApp({ println("developing iOS Application by using swift") } } fun main{ val developers = arrayListof (AndroidDeveloper (AndroidDeveloper. MobileServices.HMS) , IosDeveloper()) developers.forEach { developer -> developer.developerMobileApp() } } 

اگر

بیایید فرض کنیم که ما باید یک اپلیکیشن را برای Android و ios در شکل 1 توسعه دهیم.

آنگاه

برای رفع مشکل ، می توانیم یک interface (شکل 2) ایجاد کنیم و کلاس های AndroidDeveloper و IosDeveloper این interface را implement (پیاده سازی) خواهند کرد.

نوشته اصول S.O.L.I.D در کاتلین اولین بار در آموزشگاه اندروید ایران. پدیدار شد.

توسط asadroid

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *