2013-01-14 5 views
3

Disons que j'ai quelques contrôleurs. Chaque contrôleur peut à un moment donné créer de nouveaux objets qui devront être stockés sur le serveur. Par exemple je peux avoir un RecipeCreationViewController qui gère un formulaire. Lorsque ce formulaire est soumis, un nouvel objet Recette est créé et doit être enregistré sur le serveur.Modèle de conception de stockage en réseau

Quelle est la meilleure façon de concevoir les classes pour minimiser la complexité et le couplage tout en gardant le code aussi propre et lisible que possible?

Singleton

Normalement, je créerais un singleton NetworkAdapter que chaque contrôleur peut accéder directement afin d'enregistrer des objets.

Exemple:

[[[NetworkAdapter] sharedAdapter] saveObject:myRecipe]; 

Mais je me suis rendu compte que les classes ayant appel singletons sur leurs propres marques pour le code couplé qui est difficile à déboguer depuis l'accès au singleton est caché dans la mise en œuvre et non évidente de L'interface.

directe Référence

L'alternative est d'avoir chaque contrôleur tenir une référence au NetworkAdapter et ont cela soit passé par la classe qui crée le contrôleur.

Par exemple:

[self.networkAdapter saveObject:myRecipe]; 

Délégation

L'autre approche qui est venue à l'esprit est la délégation. Le NetworkAdapter peut implémenter un protocole "RemoteStorageDelegate" et chaque contrôleur peut avoir un remoteStorageDelegate auquel il peut appeler des méthodes comme saveObject: on. L'avantage étant que les contrôleurs ne connaissent pas les détails d'un NetworkAdapter, seulement que l'objet qui implémente le protocole sait comment sauvegarder les objets.

Par exemple:

[self.remoteStorageDelegate saveObject:myRecipe]; 

direct dans le modèle

Une autre approche serait d'avoir le modèle poignée d'économie au réseau directement. Je ne suis pas sûr si c'est une bonne idée cependant.

Par exemple:

[myRecipe save]; 

Que pensez-vous de ces? Y a-t-il d'autres modèles qui ont plus de sens pour cela?

+0

Qu'en est-il de l'injection de dépendance? –

+0

@PeterWooster Merci, je vais en lire plus à ce sujet, je ne suis toujours pas clair à 100% sur ce qu'il est encore. Si vous pouvez donner un aperçu de la façon dont vous l'appliqueriez et pourquoi, dans ce cas précis, je l'apprécierais. – nebs

+0

C'est une bonne question. Dans votre discussion sur les singletons, qu'entendez-vous par "puisque l'accès au singleton est caché dans l'implémentation et pas évident à partir de l'interface"? Bien sûr, il est caché, car la sauvegarde d'un objet est un détail d'implémentation et n'a pas besoin d'être exposé à travers l'interface. Je pense qu'un singleton est la voie à suivre, et je l'ai vu utilisé dans des projets avec succès, à la fois pour les données de base et l'accès au réseau. – Macondo2Seattle

Répondre

1

Je voudrais aussi coller avec Dependency Injection dans votre cas. Si vous voulez lire à ce sujet, vous trouverez facilement de bons articles sur le web, par ex. au Wikipedia. Fondamentalement, vous pouvez utiliser DI si vous avez deux composants ou plus, qui doivent interagir, mais ne devraient pas se connaître directement dans le code. Je vais développer un peu votre exemple, mais en style C#/Java car je ne connais pas la syntaxe Objective C.Disons que vous avez

class NetworkAdapter implements NetworkAdapterInterface { 
    void save(object o) { ... } 
} 

avec l'interface

interface NetworkAdapterInterface { 
    void save(object o); 
} 

Maintenant que vous voulez appeler cet adaptateur dans un contrôleur comme

class Controller { 
    NetworkAdapterInterface networkAdapter; 

    Controller() { 
    } 

    void setAdapter(NetworkAdapterInterface adapter) { 
    this.networkAdapter = adapter; 
    } 

    void work() { 
    this.networkAdapter.save(new object()); 
    } 
} 

Appel du Setter est où maintenant la magie de DI peut arriver (appelé Setter Injection, il y a aussi par exemple Constructor Injection). Cela signifie que vous n'avez pas une seule ligne de code où vous appelez vous-même le Setter, mais laissez-le faire le cadre DI. Très lâche couplé!

Maintenant, comment ça marche? Généralement, avec un cadre DI commun, vous pouvez définir les mappages réels entre les composants dans un emplacement de code central ou dans un fichier XML. Image que vous avez

<DI> 
    <component="NetworkAdapterInterface" class="NetworkAdapter" lifecycle="singleton" /> 
</DI> 

Cela pourrait dire le cadre de DI pour injecter automatiquement un NetworkAdapter dans tous les Setter pour NetworkAdapterInterface qu'il trouve dans votre code. Pour ce faire, il va créer l'objet approprié pour vous en premier. Si elle construit un nouvel objet pour chaque injection, ou seulement un objet pour toutes les injections (Singleton), ou par ex. un objet par Unité de travail (si vous utilisez un tel modèle), peut être configuré pour chaque type.

En tant que sidenote: Si vous testez votre code unitaire, vous pouvez également utiliser le cadre DI pour définir complètement d'autres liaisons, adaptées à votre test szenario. Un moyen facile d'injecter quelques mocks!