Interfaccia e struttura di progettazione dell'implementazione?

3

Sono abbastanza nuovo nella progettazione di programmi di grandi dimensioni in C ++. Sto scrivendo serie di operazioni, ognuna delle quali ha una propria classe, che verrà invocata dalla classe ProcessMgr .

Sto usando ProcessMgr come classe di interfaccia, da cui è possibile richiamare ogni operazione:

class ProcessMgr
{
 private:
   class OperationOne;
   class OperationTwo;
   class OperationThree;
}

class ProcessMgr::OperationOne 
{
 public:
   ...
};
class ProcessMgr::OperationTwo
{
 public:
  ...
};
class ProcessMgr::OperationThree
{
 public:
  ...
};

Questo mi consente di controllare i tipi di accesso alle classi Operation , quindi non esponendo gran parte del loro codice sottostante.

È importante che l'utente di questo codice possa interagire solo con le classi Operation in modi specifici e non avere accesso completo a tutti i contenuti delle classi Operations .

Le mie domande:

1) È un buon approccio alla progettazione di programmi di grandi dimensioni? La maggior parte delle librerie, come CURL, sono strutturate in questo modo?

2) Esistono metodi migliori / più efficienti per separare l'interfaccia e l'implementazione?

    
posta Babra Cunningham 31.01.2017 - 14:22
fonte

1 risposta

2

Preferisco utilizzare una classe di interfaccia che definisce il contratto tra il chiamante e l'implementatore. Quindi è possibile avere un numero qualsiasi di implementer della classe di interfaccia per i diversi comportamenti che potrebbero essere necessari. Tuttavia, C ++ non ha una classe di interfaccia come alcune altre lingue. Ma puoi usare una pura classe virtuale come una classe di interfaccia. Una classe virtuale pura non ha alcuna implementazione, né contiene alcuna variabile membro. Come convenzione di denominazione, mi piace mettere una capitale I davanti al nome della classe per la classe di interfaccia.

class IMyInterface
{
public:
    virtual void Function1() = 0;
    virtual boolean Function2() const = 0;
}

Quindi, le diverse implementazioni erediteranno dalla classe di interfaccia.

class MyClass1 : public IMyInterface
{
public:
    MyClass1();
    ~MyClass1();

    // IMyInterface implementation
    void Function1() override;
    boolean Function2() const override;
}

class MyClass2 : public IMyInterface
{
public:
    MyClass2();
    ~MyClass2();

    // IMyInterface implementation
    void Function1() override;
    boolean Function2() const override;
}

Le classi che devono utilizzare il servizio attraverso l'interfaccia definita accedono alla classe solo attraverso un puntatore alla classe di interfaccia.

IMyInterface* method1 = new MyClass1();
IMyInterface* method2 = new MyClass2();
method1->Function1();
method2->Function1();

Puoi anche nascondere la creazione della classe di implementazione dietro una classe factory, in modo che l'utente della classe di interfaccia sia completamente estratto dall'implementazione della classe di servizio. Tutta la classe utente sa è la classe di interfaccia. La classe di interfaccia è il contratto che dice "Fornirò queste chiamate, con i parametri elencati e restituirò il tipo indicato". L'utente dell'interfaccia non conosce o cura come viene implementata l'interfaccia o come viene svolto il lavoro. Sa solo che può chiamare le funzioni sull'interfaccia per fare il suo lavoro.

Questo è uno schema che uso un bel po '. Trovo davvero utile astrarre l'uso di una classe del tipo di servizio dalla classe del tipo di utente di quel servizio. Se segui questo schema rigorosamente, ti aiuterà a mantenere la funzionalità incapsulata.

    
risposta data 06.02.2017 - 16:54
fonte

Leggi altre domande sui tag