web-dev-qa-db-fra.com

Qu'est-ce qu'un "arrachement" dans la conception ou les modèles de logiciels?

Qu'est-ce qu'une déchirure? J'ai parcouru le terme lecture Documentation Flutter :

Renvoie un CallbackHandle qui peut être fourni à PluginUtilities.getCallbackFromHandle pour récupérer un arrachement du rappel d'origine.

Googler le terme ne semble produire que des "menus détachables" que je comprends, mais sans rapport.

3
Pete Alvin

Qu'est-ce que le schéma de "découpe"?

L'idée d'un "arrachement" est que nous avons une fonctionnalité fournie par un objet , mais la chose la fourniture de la fonctionnalité n'a pas d'identité avec le fournisseur de services auquel vous parlez .

Retournez dans les années 90 et imaginez que vous êtes un programmeur COM. COM est une norme binaire pour faire de la programmation orientée objet à partir de langages qui ne prennent pas nécessairement en charge les objets directement, comme C. La méthode fondamentale de la programmation COM est IUnknown::QueryInterface, qui prend un nombre qui identifie de manière unique une interface et échoue ou réussit en fournissant un pointeur sur un objet qui implémente cette interface. Toutes les interfaces COM héritent de IUnknown, et donc tous les objets COM implémentent QueryInterface sur toutes leurs interfaces .

Supposons donc que vous implémentiez votre serveur COM - rappelez-vous, qu'un serveur est un objet qui fournit un service ; ne considérez pas un serveur comme une machine - comme une classe C++ et vous voulez qu'il implémente IFoo et IBar, tous deux dérivant bien sûr de IUnknown. Généralement, nous le faisons en créant des classes abstraites pour IFoo et IBar, en attribuant à chacune un numéro global unique, puis en implémentant QueryInterface sur une classe C++ de telle sorte qu'elle convertit le pointeur this dans la classe abstraite appropriée et retourne le pointeur cast. La manière standard d'implémenter plusieurs interfaces est l'héritage multiple des classes de base abstraites. (Notez que même si nous logiquement préservons le référentiel identité, dans la pratique, les pointeurs peuvent être inégaux et le sont généralement.)

Mais tout ce qui est requis de QueryInterface est qu'en cas de succès, il retourne un pointeur valide vers un objet qui a la bonne table. Il n'y a pas exigence que QueryInterface soit implémenté via le transtypage en interfaces héritées de plusieurs fois. Il serait tout à fait légal pour vous de mettre en œuvre votre contrat en ayant QueryInterface renvoyer un objet différent entièrement lors de la QI pour IFoo et un objet complètement différent lorsque QI'd pour IBar. (Il y a alors quelques complications concernant ce qui se passe lorsque vous QI l'objet IFoo pour IBar, mais vous pouvez peut-être voir comment cela est géré.)

Il y a des raisons de performances et d'architecture de programme pour préférer ce choix d'implémentation, qui est appelé "interfaces à découper". L'essentiel est que lorsqu'on lui demande un service, l'objet vous remette un objet différent qui implémente ce service, plutôt que d'implémenter le service lui-même.

Du point de vue des "modèles de conception", je pense que le modèle de "découpe" est la première étape vers des solutions plus complexes à ce problème telles que la "chaîne de responsabilité". Dans la "chaîne de responsabilité", vous demandez un objet pour un service et soit il le fournit, soit il dit "Je ne peux pas fournir le service que vous voulez, mais je connais quelqu'un d'autre qui pourrait ..." et transmet la demande le long d'un chaîne de prestataires. (Dans COM, la "chaîne de responsabilité" est représentée par IServiceProvider :: QueryService.)

Il semble que Dart utilise "détacher" pour signifier quelque chose de similaire, mais uniquement pour une seule fonction , pas pour une interface entière. Autrement dit, un "arrachement" est un objet qui est distinct de l'objet d'origine, mais représente un service fourni par cet objet , à savoir la possibilité d'appeler une méthode. Je penserais à cela en C # comme un délégué .

5
Eric Lippert