Све што треба да знате о чврстим принципима у Јави



У овом чланку ћете детаљно научити шта су чврсти принципи у јави са примерима и њихов значај у стварном животу.

У свету (ООП), постоји много смерница, образаца или принципа за дизајн. Пет од ових принципа обично се групишу заједно и познати су под скраћеницом ЧВРСТО. Иако сваки од ових пет принципа описује нешто специфично, они се такође преклапају тако да усвајање једног од њих подразумева или доводи до усвајања другог. У овом чланку ћемо разумети ЧВРСТЕ принципе у Јави.

Историја ЧВРСТИХ принципа на Јави

Роберт Ц. Мартин дао је пет објектно оријентисаних принципа дизајна, а за њега се користи скраћеница „С.О.Л.И.Д“. Када комбиновано користите све принципе С.О.Л.И.Д, постаје вам лакше да развијете софтвер којим се лако може управљати. Остале карактеристике коришћења С.О.Л.И.Д су:





  • Избегава мирисе кода.
  • Брзо код рефрактора.
  • Може да се бави прилагодљивим или агилним развојем софтвера.

Када у кодирању користите принцип С.О.Л.И.Д, започињете са писањем ефикасног и делотворног кода.



Шта значи С.О.Л.И.Д?

Солид представља пет принципа Јава-а који су:

  • С. : Принцип јединствене одговорности
  • ИЛИ : Принцип отворено-затворено
  • Л : Лисков принцип замене
  • Ја : Принцип сегрегације интерфејса
  • Д. : Принцип инверзије зависности

На овом блогу ћемо детаљно размотрити свих пет СОЛИД принципа Јаве.



Принцип појединачне одговорности у Јави

Шта каже?

Роберт Ц. Мартин то описује како би једна класа требала имати само једну и једину одговорност.

Према принципу јединствене одговорности, требало би да постоји само један разлог због којег класа мора бити промењена. То значи да час треба да има један задатак. Овај принцип се често назива субјективним.

Принцип се може добро разумети на примеру. Замислите да постоји класа која изводи следеће операције.

  • Повезан са базом података

  • Прочитајте неке податке из табела базе података

  • На крају, запишите га у датотеку.

    функција сортирања у ц ++

Јесте ли замислили сценарио? Овде класа има више разлога за промену, а неколико од њих је модификација излаза датотеке, усвајање нове базе података. Када говоримо о одговорности са једним принципом, рекли бисмо да има превише разлога да се класа промени, па се она не уклапа правилно у принцип јединствене одговорности.

На пример, класа аутомобила може сама да се покрене или заустави, али задатак њеног прања припада класи ЦарВасх. У другом примеру, класа Боок има својства да чува своје име и текст. Али задатак штампања књиге мора припадати класи Штампач књига. Класа Боок Принтер се можда штампа на конзоли или неком другом медијуму, али такве зависности се уклањају из класе Боок

Зашто је потребан овај принцип?

Када се поштује принцип јединствене одговорности, тестирање је лакше. Са једном одговорношћу, разред ће имати мање тестова. Мање функционалности такође значи и мање зависности од других класа. То доводи до боље организације кода, јер је мање и добро намењене класе лакше претраживати.

Пример за појашњење овог принципа:

Претпоставимо да се од вас тражи да примените услугу УсерСеттинг у којој корисник може да промени поставке, али пре тога мора да се потврди идентитет корисника. Један од начина да се ово примени био би:

јавна класа УсерСеттингСервице {публиц воид цхангеЕмаил (Усер усер) {иф (цхецкАццесс (усер)) {// Дозвола за промену}} публиц боолеан цхецкАццесс (Усер усер) {// Проверите да ли је корисник важећи. }}

Све изгледа добро док не желите да поново користите код цхецкАццесс на неком другом месту ИЛИ ако желите да измените начин на који се врши цхецкАццесс. У сва 2 случаја на крају бисте променили исту класу, ау првом случају бисте морали да користите УсерСеттингСервице да бисте проверили и приступ.
Један од начина да се то исправи је декомпозиција УсерСеттингСервице на УсерСеттингСервице и СецуритиСервице. И преместите код цхецкАццесс у СецуритиСервице.

јавна класа УсерСеттингСервице {публиц воид цхангеЕмаил (Усер усер) {иф (СецуритиСервице.цхецкАццесс (усер)) {// Одобри опцију за промену}}} публиц цласс СецуритиСервице {публиц статиц боолеан цхецкАццесс (Усер усер) {// провери приступ. }}

Отворите затворени принцип у Јави

Роберт Ц. Мартин то описује као софтверске компоненте које би требале бити отворене за проширење, али затворене за модификације.

Прецизније, према овом принципу, класа треба да буде написана тако да свој посао обавља беспрекорно без претпоставке да ће људи у будућности једноставно доћи и променити је. Стога би класа требало да остане затворена ради модификације, али требало би да има могућност проширења. Начини продужења наставе укључују:

  • Наслеђивање из разреда

  • Преписивање потребног понашања са часа

  • Проширивање одређених понашања класе

Одличан пример принципа отворено-затворено може се разумети уз помоћ прегледача. Да ли се сећате да сте инсталирали екстензије у Цхроме прегледач?

Основна функција Цхроме прегледача је сурфовање различитим веб локацијама. Да ли желите да проверите граматику када пишете е-пошту помоћу Цхроме прегледача? Ако да, можете једноставно да користите Граммарли екстензију, она вам омогућава проверу граматике на садржају.

Овај механизам у који додајете ствари за повећање функционалности прегледача представља проширење. Отуда је прегледач савршен пример функционалности која је отворена за проширење, али је затворена за измене. Једноставним речима, можете побољшати функционалност додавањем / инсталирањем додатака у прегледачу, али не можете да направите ништа ново.

Зашто је потребан овај принцип?

ОЦП је важан јер нам часови могу доћи преко независних библиотека. Могли бисмо бити у могућности да проширимо те класе без бриге да ли те основне класе могу подржати наша проширења. Али наслеђивање може довести до подкласа које зависе од примене основне класе. Да бисте то избегли, препоручује се употреба интерфејса. Ова додатна апстракција доводи до лабавог спајања.

Рецимо да морамо израчунати површине различитих облика. Почињемо са стварањем класе за наш први облик правоугаоникакоји има 2 атрибута дужине& ширина.

правоугаоник јавне класе {јавна двострука дужина јавна двострука ширина}

Даље креирамо класу за израчунавање површине овог правоугаоникакоји има метод израчунајРецтанглеАреакоји узима Правоугаониккао улазни параметар и израчунава његову површину.

јавна класа АреаЦалцулатор {јавно двоструко израчунавањеРецтанглеАреа (правоугаоник правоугаоника) {повратак правоугаоника.дужина * правоугаоник.широкост}}

Засада је добро. Рецимо сада да добијемо круг другог облика. Тако одмах креирамо нови кружни разредса једним радијусом атрибута.

круг јавне класе {јавни двоструки радијус}

Затим модификујемо Ареацалцулаторкласа за додавање прорачуна кругова новом методом цалцуЦирцлеаАреа ()

јавна класа АреаЦалцулатор {јавни двоструки израчунРецтанглеАреа (правоугаоник правоугаоника) {повратак правоугаоника.дужина * правоугаоник.широкост} јавни двоструки израчунЦирцлеАреа (круг круга) {повратак (22/7) * круг.радиус * круг.радиус}}

Међутим, имајте на уму да је било грешака у начину на који смо горе дизајнирали наше решење.

Рецимо да имамо пентагон новог облика. У том случају ћемо опет на крају изменити класу АреаЦалцулатор. Како типови облика расту, ово постаје све месније како се АреаЦалцулатор непрестано мења и сви потрошачи ове класе мораће да наставе да ажурирају своје библиотеке које садрже АреаЦалцулатор. Као резултат тога, класа АреаЦалцулатор неће бити основа (финализована) са сигурношћу, јер ће сваки пут када дође нови облик бити модификована. Дакле, овај дизајн није затворен за модификације.

АреаЦалцулатор ће морати да настави са додавањем своје рачунске логике у новије методе. Заправо не ширимо опсег облика, већ једноставно радимо решење по комадима (мало по мало) за сваки додани облик.

Измена горе наведеног дизајна у складу са принципом отворено / затворено:

Погледајмо сада елегантнији дизајн који решава недостатке горе наведеног дизајна придржавајући се отвореног / затвореног принципа. Прво ћемо дизајн учинити проширивим. За ово морамо прво дефинисати основни тип Схапе и имати Цирцле & Рецтангле који имплементира Схапе интерфаце.

јавни интерфејс Облик {јавна двострука калкулацијаАреа ()} јавна класа Правокутник имплементира Облик {двострука дужина двострука ширина јавна двострука израчунајАреа () {повратна дужина * ширина}} јавна класа Круг имплементира Облик {јавни двоструки радијус јавна двострука израчунајАреа () {ретурн (22 / 7) * радијус * радијус}}

Постоји основни облик интерфејса. Сви облици сада примењују основни интерфејс Схапе. Интерфејс облика има апстрактну методу ЦалцуАреа (). И круг и правоугаоник пружају сопствену надјачану примену методе ЦалцуАреа () користећи сопствене атрибуте.
Донели смо степен проширивости, јер су облици сада инстанца Схапе интерфејса. То нам омогућава да користимо Схапе уместо појединачних часова
Последња тачка горе поменута потрошача ових облика. У нашем случају, потрошач ће бити класа АреаЦалцулатор која би сада изгледала овако.

јавна класа АреаЦалцулатор {јавни двоструки израчунСхапеАреа (облик облика) {ретурн схапе.цалцулатеАреа ()}}

Овај АреаЦалцулаторцласс сада у потпуности уклања наше горе наведене недостатке у дизајну и даје чисто решење које се придржава отворено-затвореног принципа. Кренимо са другим ЧВРСТИМ принципима у Јави

Лисков принцип замене у Јави

Роберт Ц. Мартин то описује као изведени типови морају бити у потпуности заменљиви основним типовима.

Лисков принцип супституције претпоставља да је к (к) својство, доказиво о ентитетима к који припада типу Т. Сада, према овом принципу, к (и) би сада требало да буде доказиво за објекте и који припадају типу С, и С је заправо подврста Т. Јесте ли сада збуњени и не знате шта заправо значи Лисков принцип замене? Његова дефиниција може бити помало сложена, али у ствари је прилично једноставна. Једина ствар је да свака подкласа или изведена класа треба да буде заменљива родитељском или основном класом.

Можете рећи да је то јединствени објектно оријентисани принцип. Начело може даље поједноставити тип детета одређеног типа родитеља, без прављења било каквих компликација или дизања ствари у ваздух, требало би да има способност да се залаже за тог родитеља. Овај принцип је уско повезан са принципом замене Лискова.

Зашто је потребан овај принцип?

Овим се избегава злоупотреба наследства. Помаже нам да се прилагодимо односу „јесте-а“. Такође можемо рећи да поткласе морају испуњавати уговор дефинисан основном класом. У том смислу је повезано саДизајн по уговоруто је први описао Бертранд Меиер. На пример, примамљиво је рећи да је круг врста елипсе, али кругови немају два фокуса или главну / молу осе.

ЛСП је популарно објашњен на примеру квадрата и правоугаоника. ако претпоставимо однос ИСА између квадрата и правоугаоника. Дакле, ми називамо „Квадрат је правоугаоник“. Доњи код представља однос.

јавна класа Правоугаоник {привате инт ленгтх привате инт ширина публиц инт гетЛенгтх () {ретурн ленгтх} јавна празнина сетЛенгтх (инт ленгтх) {тхис.ленгтх = ленгтх} публиц инт гетБреадтх () {ретурн видтхтх} јавна празнина сетБреадтх (инт ширина) { тхис.бреадтх = ширина} публиц инт гетАреа () {ретурн тхис.ленгтх * тхис.бреадтх}}

Испод је код за Скуаре. Имајте на уму да квадрат продужава правоугаоник.

јавна класа Скуаре продужава правоугаоник {јавна празнина сетБреадтх (инт ширина) {супер.сетБреадтх (ширина) супер.сетЛенгтх (ширина)} јавна празнина сетЛенгтх (инт дужина) {супер.сетЛенгтх (дужина) супер.сетБреадтх (дужина)}}

У овом случају, покушавамо да успоставимо ИСА везу између квадрата и правоугаоника тако да би позивање „Квадрат је правоугаоник“ у доњем коду почело да се понаша неочекивано ако се проследи инстанца квадрата. Грешка у тврдњи ће се појавити у случају провере за „Област“ и провера за „Ширину“, мада ће програм завршити како се грешка у тврдњи баца због неуспеха провере „Подручје“.

јавна класа ЛСПДемо {јавна празнина израчунај површину (правоугаоник р) {р.сетБреадтх (2) р.сетЛенгтх (3) потврди р.гетАреа () == 6: принтЕррор ('ареа', р) ассерт р.гетЛенгтх () == 3: принтЕррор ('ленгтх', р) ассерт р.гетБреадтх () == 2: принтЕррор ('видтх', р)} привате Стринг принтЕррор (Стринг еррорИдентифер, Рецтангле р) {ретурн 'Неочекивана вредност' + еррорИдентифер + ' на пример за '+ р.гетЦласс (). гетНаме ()} јавна статичка воид маин (Стринг [] аргс) {ЛСПДемо лсп = нев ЛСПДемо () // Примерак Рецтангле прослеђује се лсп.цалцулатеАреа (нев Рецтангле ()) // Примерак квадрата се прослеђује лсп.цалцулатеАреа (нови Скуаре ())}}

Разред демонстрира Лисков принцип замене (ЛСП) Према принципу, функције које користе референце на основне класе морају бити у могућности да користе објекте изведене класе, а да то не знају.

Дакле, у примеру приказаном доле, функција израчунајте површину која користи референцу „Правоугаоник“ требало би да може да користи објекте изведене класе као што је квадрат и да испуни захтев постављен дефиницијом правоугаоника. Треба имати на уму да, према дефиницији правоугаоника, следеће мора увек бити тачно с обзиром на податке у наставку:

  1. Дужина мора увек бити једнака дужини прослеђеној као улаз у методу сетЛенгтх
  2. Ширина мора увек бити једнака ширини прослеђеној као улаз у методу, сетБреадтх
  3. Површина мора увек бити једнака производу дужине и ширине

У случају да покушамо успоставити ИСА везу између квадрата и правокутника тако да зовемо „квадрат је правоугаоник“, горњи код би се почео неочекивано понашати ако се прође инстанца квадрата. У случају провере површине и провере избациће се грешка у тврдњи за ширину, иако ће се програм завршити јер се погрешка у тврдњи баци због неуспеха провере подручја.

Класи Скуаре нису потребне методе попут сетБреадтх или сетЛенгтх. Класа ЛСПДемо требала би знати детаље изведених класа правоугаоника (као што је квадрат) да би их прикладно кодирала како би се избегла грешка у бацању. Промена постојећег кода пре свега нарушава принцип отворено-затворено.

Принцип сегрегације интерфејса

Роберт Ц. Мартин то описује како клијенте не треба присиљавати да примењују непотребне методе које неће користити.

ПремаПринцип сегрегације интерфејсаклијента, без обзира на то шта никада не би требало приморати да имплементира интерфејс који он не користи или клијент никада не би требало да буде обавезан да зависи од било које методе коју они не користе. Дакле, у основи, принципи сегрегације интерфејса, како више волите интерфејси, који су мали, али специфични за клијента уместо монолитног и већег интерфејса. Укратко, било би лоше да приморате клијента да зависи од одређене ствари која им није потребна.

На пример, један интерфејс за евидентирање за писање и читање дневника користан је за базу података, али не и за конзолу. Читање дневника нема смисла за записник конзоле. Настављајући са овим ЧВРСТИ принципи у чланку Јава.

Зашто је потребан овај принцип?

Рецимо да постоји ресторан интерфејс који садржи методе за прихватање поруџбина интернетских купаца, диал-ин или телефонских купаца и валк-ин купаца. Такође садржи методе за руковање онлајн плаћањем (за мрежне купце) и личним плаћањем (за купце који улазе као и за телефонске купце када им се наруџба испоручује код куће).

Сада креирајмо Јава интерфејс за ресторан и назовимо га РестаурантИнтерфаце.јава.

јавни интерфејс РестаурантИнтерфаце {јавна празнина аццептОнлинеОрдер () јавна празнина такеТелепхонеОрдер () јавна празнина паиОнлине () јавна празнина валкИнЦустомерОрдер () јавна празнина паиИнПерсон ()}

У РестаурантИнтерфаце-у је дефинисано 5 метода за прихватање онлајн наруџбине, преузимање телефонске наруџбине, прихватање наруџби од корисника који улази, прихватање онлајн плаћања и лично прихватање плаћања.

Почнимо са применом РестаурантИнтерфаце за мрежне купце као ОнлинеЦлиентИмпл.јава

јавна класа ОнлинеЦлиентИмпл имплементира РестаурантИнтерфаце {публиц воид аццептОнлинеОрдер () {// логика за наручивање путем интернета} публиц воид такеТелепхонеОрдер () {// Није применљиво за онлајн наруџбу баца нову УнсуппортедОператионЕкцептион ()} јавну воид паиОнлине () {// логику за плаћање онлајн} јавна воид валкИнЦустомерОрдер () {// Није применљиво за онлајн наруџбину бацање новог УнсуппортедОператионЕкцептион ()} јавна воид паиИнПерсон () {// Није применљиво за онлајн наруџбину бацање новог УнсуппортедОператионЕкцептион ()}}
  • Будући да је горњи код (ОнлинеЦлиентИмпл.јава) намењен мрежним поруџбинама, баците УнсуппортедОператионЕкцептион.

  • Интернет, телефонски и валк-ин клијенти користе имплементацију РестаурантИнтерфаце специфичну за сваког од њих.

  • Класе имплементације за телефонског клијента и Валк-ин клијента имаће неподржане методе.

  • С обзиром да је 5 метода део РестаурантИнтерфаце-а, класе имплементације морају да примене свих 5.

  • Методе које свака од класа имплементације баца УнсуппортедОператионЕкцептион. Као што јасно видите - примена свих метода је неефикасна.

  • Свака промена било ког од метода РестаурантИнтерфаце-а пренеће се на све класе имплементације. Одржавање кода тада почиње да постаје заиста гломазно и регресијски ефекти промена ће се повећавати.

    постдипломски сертификат вс мастер
  • РестаурантИнтерфаце.јава крши принцип јединствене одговорности јер су логика плаћања и логика за наручивање груписане у један интерфејс.

Да бисмо превазишли горе поменуте проблеме, примењујемо принцип сегрегације интерфејса за рефакторирање горњег дизајна.

  1. Раздвојите функционалности плаћања и налога за плаћање у два одвојена витка интерфејса, ПаиментИнтерфаце.јава и ОрдерИнтерфаце.јава.

  2. Сваки од клијената користи по једну имплементацију ПаиментИнтерфаце и ОрдерИнтерфаце. На пример - ОнлинеЦлиент.јава користи ОнлинеПаиментИмпл и ОнлинеОрдерИмпл итд.

  3. Принцип појединачне одговорности сада је приложен као интерфејс за плаћање (ПаиментИнтерфаце.јава) и интерфејс за наручивање (ОрдерИнтерфаце).

  4. Промена било ког интерфејса налога или плаћања не утиче на други. Они су сада независни. Неће бити потребно радити било какву лажну имплементацију или бацати УнсуппортедОператионЕкцептион, јер сваки интерфејс има само методе које ће увек користити.

Након примене ИСП-а

Принцип инверзије зависности

Роберт Ц. Мартин то описује јер то зависи од апстракција, а не од бетона. Према њему, модул високог нивоа никада се не сме ослањати ни на један модул ниског нивоа. на пример

Одете у локалној продавници да купите нешто и одлучите да платите дебитном картицом. Дакле, када картици дате службеницу за извршење плаћања, службеник се не труди да провери какву сте картицу дали.

Чак и ако сте дали Виса картицу, он неће угасити Виса машину за превлачење ваше картице. Врста кредитне или дебитне картице коју плаћате није ни битна јер ће је једноставно превући. Дакле, у овом примеру можете видети да и ви и службеник зависите од апстракције кредитне картице и да вас не брину специфичности картице. То је оно што је принцип инверзије зависности.

Зашто је потребан овај принцип?

Омогућава програмеру да уклони кодиране зависности тако да апликација постаје лабаво повезана и проширива.

јавни разред студент {приватна адреса Адреса публиц Студент () {адреса = нова адреса ()}}

У горњем примеру, класа Студент захтева објект Аддресс и она је одговорна за иницијализацију и употребу објекта Аддресс. Ако се адреса класе промени у будућности, тада морамо извршити промене и у класи ученика. Ово чини уску спрегу између предмета Студент и Аддресс. Овај проблем можемо решити помоћу обрасца дизајна инверзије зависности. тј. Адресни објекат ће се имплементирати независно и пружити ће се студенту када се студент покрене помоћу примене инверзије зависности засноване на конструктору или сетеру.

Овим смо дошли до краја ових ЧВРСТИХ принципа у Јави.

Погледајте Едурека, поуздана компанија за учење на мрежи са мрежом од више од 250.000 задовољних ученика раширених широм света. Едурекин курс за обуку и сертификацију Јава Ј2ЕЕ и СОА дизајниран је за студенте и професионалце који желе да буду Јава програмер. Курс је дизајниран да вам пружи почетну предност у Јава програмирању и обучи вас како за основне тако и за напредне Јава концепте, заједно са разним Јава оквирима попут Хибернате & Спринг.

Имате питање за нас? Молимо вас да га помињете у одељку за коментаре овог блога „ЧВРСТИ Принципи у Јави“ и јавићемо вам се што је пре могуће.