it-swarm-eu.dev

Co je princip závislosti inverze a proč je to důležité?

Co je princip závislosti inverze a proč je to důležité?

163
Phillip Wells

Zaškrtněte tento dokument: Princip inverzní závislosti .

V podstatě říká:

  • Moduly na vysoké úrovni by neměly záviset na nízkoúrovňových modulech. Oba by měli záviset na abstrakcích.
  • Abstrakce by nikdy neměly záviset na detailech. Podrobnosti by měly záviset na abstrakcích.

Pokud jde o to, proč je důležité, zkrátka: změny jsou riskantní, a v závislosti na koncepci namísto na implementaci, snižujete potřebu změny na stránkách volání.

DIP efektivně snižuje spojení mezi různými kódy. Myšlenka spočívá v tom, že i když existuje mnoho způsobů, jak zavést, např. Protokolovat zařízení, způsob, jakým byste jej používali, by měl být v čase poměrně stabilní. Pokud můžete extrahovat rozhraní, které představuje koncept protokolování, toto rozhraní by mělo být mnohem stabilnější v čase, než je jeho implementace, a stránky volání by měly být mnohem méně ovlivněny změnami, které můžete provést při zachování nebo rozšíření tohoto mechanismu protokolování.

Díky tomu, že implementace závisí na rozhraní, získáte možnost zvolit si v době běhu, která implementace je vhodnější pro vaše konkrétní prostředí. V závislosti na případech to může být také zajímavé.

102
Carl Seleborg

Knihy Agile Software Development, Principles, Patterns a Practices a Agile Principles, Patterns a Practices v C # jsou nejlepším zdrojem pro plné pochopení původních cílů a motivací principu závislosti závislostí. Dobrým zdrojem je také článek „Princip závislostí na inverzních závislostech“, ale vzhledem k tomu, že se jedná o zhuštěnou verzi návrhu, který nakonec vstoupil do dříve zmíněných knih, zanechává důležitou diskusi o koncepci vlastnictví balíčků a rozhraní, které jsou klíčem k rozlišení tohoto principu od obecnějšího doporučení „programovat rozhraní, nikoli implementaci“, které se nachází v knize Návrhové vzory (Gamma, et al.).

Chcete-li poskytnout souhrn, princip Závislostní inverze je primárně o obrácení konvenčního směru závislostí ze složek "vyšší úrovně" na komponenty "nižší úrovně", takže komponenty "nižší úrovně" jsou závislé na rozhraních vlastněných složkami "vyšší úrovně". (Poznámka: složka "vyšší úroveň" zde označuje komponentu, která vyžaduje externí závislosti/služby, ne nutně její koncepční pozici v rámci vrstvené architektury.) Tímto způsobem není spojování sníženo tak, jak je posunuté ze složek, které jsou teoreticky méně cenné pro komponenty, které jsou teoreticky hodnotnější.

Toho je dosaženo návrhem komponent, jejichž vnější závislosti jsou vyjádřeny v podmínkách rozhraní, pro které musí být implementace poskytována spotřebitelem komponenty. Jinými slovy, definovaná rozhraní vyjadřují, co komponenta potřebuje, nikoli způsob, jakým komponentu používáte (např. "INeedSomething", nikoli "IDoSomething").

Princip Závislosti Inverze se nevztahuje na jednoduchou praxi oddělování závislostí pomocí rozhraní (např. MyService → [ILogger ger Logger]). I když to odděluje komponentu od specifického detailu implementace závislosti, neinvertuje vztah mezi spotřebitelem a závislostí (např. [MyService → IMyServiceLogger] ger Logger.

Důležitost principu závislosti závislostí může být destilována do jediného cíle, kterým je schopnost znovu použít softwarové komponenty, které jsou závislé na vnějších závislostech na části své funkce (protokolování, ověřování atd.) 

V rámci tohoto obecného cíle opakovaného použití můžeme vymezit dva podtypy opakovaného použití: 

  1. Použití softwarové komponenty v rámci více aplikací s implementacemi závislostí (např. Vyvinuli jste kontejner DI a chcete poskytovat protokolování, ale nechcete svůj kontejner spojovat s konkrétním loggerem, takže každý, kdo používá váš kontejner, musí také použít vybranou knihovnu protokolování).

  2. Používání softwarových komponent v vyvíjejícím se kontextu (např. Jste vyvinuli komponenty obchodní logiky, které zůstávají stejné ve více verzích aplikace, kde se vyvíjejí podrobnosti implementace). 

S prvním případem opětovného použití komponent ve více aplikacích, například s knihovnou infrastruktury, je cílem poskytnout vašim zákazníkům základní potřebu infrastruktury bez propojení vašich spotřebitelů se závislostmi vaší vlastní knihovny, protože závislost na takových závislostech vyžaduje vaše spotřebitelé požadovat stejné závislosti. To může být problematické, když se spotřebitelé vaší knihovny rozhodnou použít jinou knihovnu pro stejné potřeby infrastruktury (např. NLog vs. log4net), nebo pokud se rozhodnou použít novější verzi požadované knihovny, která není zpětně kompatibilní s verzí požadované vaší knihovnou.

Druhým případem opětovného použití komponent logiky (tj. „Komponenty vyšší úrovně“) je izolovat implementaci jádra vaší aplikace od měnících se potřeb vašich implementačních detailů (tj. Změna/upgrade knihoven perzistence, knihoven zpráv , atd.). V ideálním případě by změna implementačních detailů aplikace neměla narušovat komponenty, které obsahují obchodní logiku aplikace.

Poznámka: Někteří mohou namítat, že se tento druhý případ bude popisovat jako skutečné opakované použití, přičemž argumentuje tím, že komponenty, jako jsou komponenty obchodní logiky používané v rámci jedné vyvíjející se aplikace, představují pouze jedno použití. Myšlenka zde však spočívá v tom, že každá změna implementačních detailů aplikace činí nový kontext, a tedy i jiný případ použití, ačkoli konečné cíle by mohly být rozlišeny jako izolace vs. přenositelnost.

Zatímco v tomto druhém případě může princip principu Závislosti na inverzi nabídnout určitou výhodu, je třeba poznamenat, že jeho hodnota, jak je aplikována na moderní jazyky, jako je Java a C #, je mnohem menší, možná až do bodu, kdy je irelevantní. Jak bylo zmíněno dříve, DIP zahrnuje úplné oddělení implementačních detailů do samostatných balíčků. V případě vyvíjející se aplikace však bude jednoduché používání rozhraní definovaných v rámci obchodní domény chránit před potřebou měnit komponenty vyšší úrovně kvůli měnícím se potřebám komponent detailů implementace, i když detaily implementace nakonec spadají do stejného balíčku. Tato část principu odráží aspekty, které se týkaly jazyka, když byl princip kodifikován (tj. C++), které nejsou relevantní pro novější jazyky. To znamená, že význam principu Závislosti Inverze spočívá především ve vývoji opakovaně použitelných softwarových komponent/knihoven.

Delší diskuse o tomto principu, která se týká jednoduchého použití rozhraní, závislostního vstřikování a vzoru odděleného rozhraní, lze nalézt zde .

131
Derek Greer

Když navrhujeme softwarové aplikace, můžeme uvažovat třídy s nízkou úrovní třídy, které implementují základní a primární operace (přístup na disk, síťové protokoly, ...) a třídy na vysoké úrovni třídy, které obsahují komplexní logiku (obchodní toky, ...).

Poslední se spoléhají na třídy s nízkou úrovní. Přirozeným způsobem implementace takových struktur by bylo psát třídy na nízké úrovni a jednou bychom je měli psát komplexní třídy na vysoké úrovni. Vzhledem k tomu, že třídy na vysoké úrovni jsou definovány z hlediska ostatních, je to logický způsob, jak to udělat. Ale to není flexibilní design. Co se stane, když budeme muset nahradit nízkou úroveň?

Princip inverzní závislosti uvádí, že:

  • Moduly vysoké úrovně by neměly záviset na modulech nízké úrovně. Oba by měli záviset na abstrakcích.
  • Abstrakce by neměly záviset na detailech. Podrobnosti by měly záviset na abstrakcích.

Tento princip se snaží „invertovat“ konvenční představu, že moduly na vysoké úrovni v softwaru by měly záviset na modulech nižší úrovně. Zde moduly na vysoké úrovni vlastní abstrakci (například rozhodování o metodách rozhraní), které jsou implementovány moduly nižší úrovně. Díky tomu jsou moduly nižší úrovně závislé na modulech vyšší úrovně.

10
nikhil.singhal

Použitá inverze závislostí poskytuje flexibilitu a stabilitu na úrovni celé architektury vaší aplikace. To umožní vaší aplikaci vyvíjet se bezpečněji a stabilněji.

Tradiční vrstvená architektura

Tradičně vrstvené architektury UI záviselo na obchodní vrstvě a to zase záviselo na datové vrstvě.

http://xurxodev.com/content/images/2016/02/Traditional-Layered.png

Musíte rozumět vrstvě, balíčku nebo knihovně. Podívejme se, jak by kód byl.

Měli bychom knihovnu nebo balíček pro vrstvu přístupu k datům.

// DataAccessLayer.dll
public class ProductDAO {

}

A další obchodní logiku nebo vrstvu obchodní vrstvy, která závisí na vrstvě přístupu k datům.

// BusinessLogicLayer.dll
using DataAccessLayer;
public class ProductBO { 
    private ProductDAO productDAO;
}

Vrstvená architektura s inverzí závislosti

Inverze závislostí označuje následující:

Moduly na vysoké úrovni by neměly záviset na modulech nízké úrovně. Oba by měli záviset na abstrakcích.

Abstrakce by neměly záviset na detailech. Podrobnosti by měly záviset na abstrakcích.

Jaké jsou moduly na vysoké úrovni a nízká úroveň? Moduly, jako jsou knihovny nebo balíčky, by měly být modulem na vysoké úrovni, který má tradičně závislost a nízkou úroveň, na které závisí.

Jinými slovy, vysoká úroveň modulu by byla tam, kde je akce vyvolána a nízká úroveň, kde se akce provádí.

Z tohoto principu je rozumný závěr, že by neměla existovat závislost mezi konkretizacemi, ale musí existovat závislost na abstrakci. Ale podle přístupu, který bereme, můžeme být závislí na investicích, ale abstrakci.

Představte si, že náš kód přizpůsobíme takto:

Měli bychom knihovnu nebo balíček pro vrstvu přístupu k datům, která definuje abstrakci.

// DataAccessLayer.dll
public interface IProductDAO
public class ProductDAO : IProductDAO{

}

A další obchodní logiku nebo vrstvu obchodní vrstvy, která závisí na vrstvě přístupu k datům.

// BusinessLogicLayer.dll
using DataAccessLayer;
public class ProductBO { 
    private IProductDAO productDAO;
}

I když jsme závislí na abstrakční závislosti mezi obchodem a datovým přístupem, zůstává stejný.

http://xurxodev.com/content/images/2016/02/Traditional-Layered.png

Chcete-li získat inverzi závislosti, musí být v modulu nebo balíčku definováno rozhraní perzistence, kde tato logika vysoké úrovně nebo doména je a není v modulu nízké úrovně.

Nejdříve definujte, co je to vrstva domény a abstrakce její komunikace je definována jako perzistence.

// Domain.dll
public interface IProductRepository;

using DataAccessLayer;
public class ProductBO { 
    private IProductRepository productRepository;
}

Po vytrvalostní vrstva závisí na doméně, dostat se invertovat nyní, pokud je definována závislost.

// Persistence.dll
public class ProductDAO : IProductRepository{

}

http://xurxodev.com/content/images/2016/02/Dependency-Inversion-Layers.png

Prohloubení principu

Je důležité tento koncept dobře asimilovat, prohloubit jeho účel a přínosy. Pokud zůstaneme v mechanice a naučíme se typickým případovým úložištěm, nebudeme schopni určit, kde můžeme aplikovat princip závislosti.

Proč však převracíme závislost? Jaký je hlavní cíl nad rámec konkrétních příkladů?

Takovéto obyčejné umožňuje častější změny nejstabilnějších věcí, které nejsou závislé na méně stabilních věcech.

Je snazší změnit typ perzistence, buď databázi nebo technologii pro přístup ke stejné databázi, než logika domény nebo akce určené pro komunikaci s perzistencí. Z tohoto důvodu je závislost obrácena, protože je snazší změnit perzistenci, pokud k této změně dojde. Tímto způsobem nebudeme muset doménu měnit. Vrstva domény je nejstabilnější ze všech, proto by neměla záviset na ničem.

Neexistuje však jen tento příklad úložiště. Existuje mnoho scénářů, kde se tento princip uplatňuje a existují architektury založené na tomto principu.

Architektury

Tam jsou architektury kde závislost inverze je klíč k jeho definici. Ve všech doménách je to nejdůležitější a jsou to abstrakce, které označují komunikační protokol mezi doménou a zbytkem balíčků nebo knihoven.

Čistá architektura

V Čistá architektura doména se nachází ve středu a pokud se podíváte ve směru šipek označujících závislost, je jasné, jaké jsou nejdůležitější a nejstabilnější vrstvy. Vnější vrstvy jsou považovány za nestabilní nástroje, takže se na nich nemusíte spoléhat.

Šestihranná architektura

Stává se stejným způsobem s hexagonální architekturou, kde se doména nachází také v centrální části a porty jsou abstrakcemi komunikace z domina ven. Zde je opět zřejmé, že doména je nejstabilnější a tradiční závislost je invertována.

9
xurxodev

Princip závislostí na závislost, jak je popsán v oficiálním článku , je pro mě opravdu zavádějící pokus o zvýšení opakované použitelnosti modulů, které jsou v podstatě méně opakovaně použitelné, a také způsob řešení problému v jazyce C++. Jazyk.

Problém v C++ je, že soubory záhlaví obvykle obsahují deklarace soukromých polí a metod. Proto pokud modul C++ na vysoké úrovni obsahuje soubor záhlaví pro modul nízké úrovně, bude záviset na skutečném implementace podrobnosti o tomto modulu. A to samozřejmě není dobrá věc. Ale to není problém v modernějších jazycích běžně používaných dnes.

Moduly na vysoké úrovni jsou ve své podstatě méně opakovaně použitelné než moduly na nízké úrovni, protože tyto moduly jsou obvykle více specifické pro konkrétní aplikace než kontextové moduly. Například součást, která implementuje obrazovku uživatelského rozhraní, je na nejvyšší úrovni a také velmi (zcela?) Specifická pro aplikaci. Pokus o opakované použití takové komponenty v jiné aplikaci je kontraproduktivní a může vést pouze k nadměrnému inženýrství.

Vytvoření samostatné abstrakce na stejné úrovni komponenty A, která závisí na komponentě B (která není závislá na A), může být tedy provedeno pouze v případě, že komponenta A bude skutečně užitečná pro opakované použití v různých aplikacích nebo kontextech. Pokud tomu tak není, pak by použití DIP bylo špatné provedení.

9
Rogério

V podstatě říká:

Třída by měla záviset na abstrakcích (např. Rozhraní, abstraktních třídách), ne na konkrétních detailech (implementacích).

8
martin.ra

Mnohem jasnější způsob, jak uvést princip inverze závislosti je:

Vaše moduly, které obsahují komplexní obchodní logiku, by neměly záviset přímo na jiných modulech, které zapouzdřují obchodní logiku. Místo toho by měly záviset pouze na rozhraních s jednoduchými daty.

Tedy místo toho, aby se vaše třída Logic implementovala jako obvykle:

class Dependency { ... }
class Logic {
    private Dependency dep;
    int doSomething() {
        // Business logic using dep here
    }
}

měli byste udělat něco jako:

class Dependency { ... }
interface Data { ... }
class DataFromDependency implements Data {
    private Dependency dep;
    ...
}
class Logic {
    int doSomething(Data data) {
        // compute something with data
    }
}

Data a DataFromDependency by měly žít ve stejném modulu jako Logic, nikoli s Dependency.

Proč tohle?

  1. Dva moduly obchodní logiky jsou nyní odpojeny. Když Dependency změny, nemusíte měnit Logic
  2. Pochopení toho, co Logic dělá, je mnohem jednodušší úkol: funguje pouze na tom, co vypadá jako ADT.
  3. Logic lze nyní snadněji testovat. Nyní můžete přímo vytvořit instanci Data s falešnými daty a předat ji dál.
5
mattvonb

Dobré odpovědi a dobré příklady jsou již uvedeny ostatními.

Důvod DIP je důležitý, protože zajišťuje OO-princip "volně spojený design".

Objekty ve vašem softwaru by se neměly dostat do hierarchie, kde jsou některé objekty na nejvyšší úrovni závislé na objektech nízké úrovně. Změny v nízkoúrovňových objektech se pak převedou na objekty nejvyšší úrovně, což činí software velmi křehkým pro změnu.

Chcete, aby vaše objekty na nejvyšší úrovni byly velmi stabilní a ne křehké pro změnu, proto je nutné tyto závislosti převrátit.

5
Hace

Inverze kontroly (IoC) je návrhový vzor, ​​kde objekt získá svou závislost spíše vnějším rámcem než žádáním o rámec pro jeho závislost.

Příklad pseudokódu pomocí tradičního vyhledávání:

class Service {
    Database database;
    init() {
        database = FrameworkSingleton.getService("database");
    }
}

Podobný kód pomocí IoC:

class Service {
    Database database;
    init(database) {
        this.database = database;
    }
}

Výhody IoC jsou:

  • Nemáte žádnou závislost na centrálním Rámci, takže to lze změnit, pokud chcete .
  • Vzhledem k tomu, že objekty jsou vytvořeny Injekcí, s výhodou pomocí rozhraní , Je snadné vytvořit testy jednotek , Které nahrazují závislosti s Falešnými verzemi.
  • Odpojovací kód.
5
Staale

Bodem závislosti inverze je vytvořit opakovaně použitelný software.

Myšlenka je, že namísto dvou kusů kódu spoléhajících se na sebe se spoléhají na některé abstraktní rozhraní. Pak můžete znovu použít jeden kus bez druhého.

Nejčastěji se toho dosahuje pomocí inverzní kontroly (IoC), jako je jaro v Javě. V tomto modelu jsou vlastnosti objektů nastaveny pomocí konfigurace XML namísto toho, aby objekty procházely a hledaly jejich závislost.

Představte si tento pseudokód ...

public class MyClass
{
  public Service myService = ServiceLocator.service;
}

MyClass přímo závisí na třídě Service a třídě ServiceLocator. Pokud ho chcete použít v jiné aplikaci, potřebuje oba. Představte si to ...

public class MyClass
{
  public IService myService;
}

Nyní se MyClass spoléhá na jediné rozhraní, rozhraní IService. Nechali jsme kontejner IoC skutečně nastavit hodnotu této proměnné.

Takže nyní, MyClass může být snadno znovu použit v jiných projektech, aniž by s sebou přinesla závislost těchto dvou tříd.

Ještě lépe, nemusíte přetahovat závislosti MyService a závislosti na těchto závislostech a ... no, máte nápad.

1
Marc Hughes

Inverze kontrolních kontejnerů a vzor závislosti závislosti Martin Fowler je také dobrým čtením. Našel jsem Head First Design Patterns úžasnou knihu pro můj první vpád do učení DI a dalších vzorů.

1
Chris Canal

Myslím, že mám mnohem lepší (intuitivnější) příklad.

  • Představte si systém (webapp) se správou zaměstnanců a kontaktů (dvě obrazovky).
  • Nejsou přesně spojeny, takže je chcete mít ve svém vlastním modulu/složce

Takže byste měli mít nějaký "hlavní" vstupní bod, který by musel vědět o modulu Řízení zaměstnanců a Kontaktní modul pro správu a musel by poskytovat odkazy v navigaci a přijímat žádosti o api atd. Jinými slovy hlavní modul by závisel na těchto dvojicích - věděl by o jejich řadičích, trasách a odkazech, které musí být vykresleny v (sdílené) navigaci.

Příklad Node.js

// main.js
import express from 'express'

// two modules, each having many exports
import { api as contactsApi, navigation as cNav } from './contacts/'
import { api as employeesApi, navigation as eNav } from './employees/'

const api = express()
const navigation = {
  ...cNav,
  ...eNav
}

api.use('contacts', contactsApi)
api.use('employees', employeesApi)

// do something with navigation, possibly do some other setup

Všimněte si prosím existují případy (jednoduché), když je to naprosto v pořádku.


Takže v průběhu času se dostane do bodu, kdy není tak triviální přidat nové moduly. Musíte pamatovat na registraci api, navigace, možná oprávnění , a tento main.js se zvětší a zvětší.

A to je místo, kde přichází inverze závislosti. Místo toho, aby byl váš hlavní modul závislý na všech ostatních modulech, zavedete nějaké „jádro“ a každý modul se zaregistrujete.

Takže v tomto případě jde o to, že máme představu o nějakém ApplicationModulu, který se může podrobit mnoha službám (trasy, navigace, oprávnění) a hlavní modul může zůstat jednoduchý (stačí importovat modul a nechat jej nainstalovat)

Jinými slovy, jde o to, aby byla architektura připojitelná. To je další práce a kód budete muset psát/číst a udržovat, takže byste neměli dělat to předem, ale spíše, když máte tento druh vůně.

Co je obzvláště zajímavé je, že můžete udělat něco plugin, dokonce i vytrvalost vrstvy - které by mohly být stojí za to dělat, pokud potřebujete podporovat mnoho implementací vytrvalosti, ale to obvykle není případ. Podívejte se na další odpověď na obrázek s hexagonální architekturou, je to skvělé pro ilustraci - existuje jádro a všechno ostatní je v podstatě plugin.

0
Kamil Tomšík

Závislost inverze: Závisí na abstrakcích, nikoliv na konkrementech.

Inverze kontroly: Main vs Abstrakce, a jak hlavní je lepidlo systémů.

DIP and IoC

Toto jsou některé dobré příspěvky, které o tom mluví:

https://coderstower.com/2019/03/26/dependency-inversion-why-you-shouldnt-avoid-it/

https://coderstower.com/2019/04/02/main-and-abstraction-the-decoupled-peers/

https://coderstower.com/2019/04/09/inversion-of-control-putting-all-together/

Kromě dalších odpovědí.

Dovolte mi nejprve uvést příklad.

Nechte tam být hotel, který požádá o generátor potravin pro jeho dodávky. Hotel dává název jídla (řekněme kuře) generátoru potravin a generátor vrací požadované jídlo hotelu. Hotel se však nestará o druh jídla, které přijímá a podává. Generátor tedy dodává do hotelu potraviny s označením "Jídlo".

Tato implementace je v Javě

FactoryClass s výrobní metodou. Generátor potravin

public class FoodGenerator {
    Food food;
    public Food getFood(String name){
        if(name.equals("fish")){
            food =  new Fish();
        }else if(name.equals("chicken")){
            food =  new Chicken();
        }else food = null;

        return food;
    }
}


Abstrakt/třída rozhraní

public abstract class Food {

    //None of the child class will override this method to ensure quality...
    public void quality(){
        String fresh = "This is a fresh " + getName();
        String tasty = "This is a tasty " + getName();
        System.out.println(fresh);
        System.out.println(tasty);
    }
    public abstract String getName();
}


Kuře zavádí potraviny (třída betonu)

public class Chicken extends Food {
    /*All the food types are required to be fresh and tasty so
     * They won't be overriding the super class method "property()"*/

    public String getName(){
        return "Chicken";
    }
}


Ryby realizují potraviny (třída betonu)

public class Fish extends Food {
    /*All the food types are required to be fresh and tasty so
     * They won't be overriding the super class method "property()"*/

    public String getName(){
        return "Fish";
    }
}


Konečně

Hotel

public class Hotel {

    public static void main(String args[]){
        //Using a Factory class....
        FoodGenerator foodGenerator = new FoodGenerator();
        //A factory method to instantiate the foods...
        Food food = foodGenerator.getFood("chicken");
        food.quality();
    }
}

Jak můžete vidět, Hotel neví, zda se jedná o kuřecí předmět nebo rybí objekty. Pouze ví, že se jedná o potravinový objekt, tj. Hotel závisí na třídě potravin.

Také byste si všimli, že ryby a kuřecí třída implementuje třídu Food a není přímo spojena s hotelem. Kuře a ryby také závisí na třídě potravin.

Což znamená, že složka na vysoké úrovni (Hotel) a komponenta na nízké úrovni (Fish and Chicken) závisí na abstrakci (Food).

Toto se nazývá inverze závislosti. 

0
Revolver

Princip Dependency Inversion (DIP) říká, že 

i) Moduly vysoké úrovně by neměly záviset na modulech nízké úrovně. Oba by měli záviset na abstrakcích.

ii) Abstrakce by nikdy neměly záviset na detailech. Podrobnosti by měly záviset na abstrakcích.

Příklad: 

    public interface ICustomer
    {
        string GetCustomerNameById(int id);
    }

    public class Customer : ICustomer
    {
        //ctor
        public Customer(){}

        public string GetCustomerNameById(int id)
        {
            return "Dummy Customer Name";
        }
    }

    public class CustomerFactory
    {
        public static ICustomer GetCustomerData()
        {
            return new Customer();
        }
    }

    public class CustomerBLL
    {
        ICustomer _customer;
        public CustomerBLL()
        {
            _customer = CustomerFactory.GetCustomerData();
        }

        public string GetCustomerNameById(int id)
        {
            return _customer.GetCustomerNameById(id);
        }
    }

    public class Program
    {
        static void Main()
        {
            CustomerBLL customerBLL = new CustomerBLL();
            int customerId = 25;
            string customerName = customerBLL.GetCustomerNameById(customerId);


            Console.WriteLine(customerName);
            Console.ReadKey();
        }
    }

Poznámka: Třída by měla záviset na abstrakcích jako jsou rozhraní nebo abstraktní třídy, nikoli konkrétní podrobnosti (implementace rozhraní).

0
Rejwanul Reja