Table des matières
总结
Maison Java javaDidacticiel Java implémente le partage d'exemples de code en utilisant la réflexion en mode visiteur

Java implémente le partage d'exemples de code en utilisant la réflexion en mode visiteur

Mar 23, 2017 am 11:13 AM

Le type de collection est en Orienté vers les Objetsprogrammation est très couramment utilisée, ce qui amène également quelques questions liées au code, telles que : « Comment faire fonctionner différents types d'objets dans la collection ? ”

Une approche consiste à parcourir chaque élément de la collection, puis à effectuer des opérations spécifiques en fonction de son type. Cela sera très compliqué, surtout lorsque vous ne connaissez pas le type des éléments de la collection. Si vous souhaitez imprimer les éléments de la collection, vous pouvez écrire une méthode comme celle-ci :

public void messyPrintCollection(Collection collection) {
    Iterator iterator = collection.iterator()
    while (iterator.hasNext())
        System.out.println(iterator.next().toString())
}
Copier après la connexion
Cela semble simple d'appeler simplement la méthode Object.toString() et d'imprimer l'objet, n'est-ce pas ? et si votre collection ? Qu'en est-il d'un vecteur contenant une table de hachage ? Cela devient plus compliqué. Vous devez vérifier le type de l'objet retourné par la collection :

public void messyPrintCollection(Collection collection) {
    Iterator iterator = collection.iterator()
    while (iterator.hasNext()) {
        Object o = iterator.next();
        if (o instanceof Collection)
            messyPrintCollection((Collection)o);
        else
            System.out.println(o.toString());
        }
}
Copier après la connexion
D'accord, vous pouvez maintenant gérer les objets de collection imbriqués, mais d'autres objets

String n'est pas ce que vous voulez ? Si vous souhaitez ajouter des guillemets à l'objet chaîne et ajouter un f après l'objet Float, que devez-vous faire ? 🎜>

Le code devient très vite compliqué. Vous ne voulez pas avoir un tas d'instructions if-else dans votre code ! Comment le
public void messyPrintCollection(Collection collection) {
    Iterator iterator = collection.iterator()
    while (iterator.hasNext()) {
        Object o = iterator.next();
        if (o instanceof Collection)
            messyPrintCollection((Collection)o);
        else if (o instanceof String)
            System.out.println("'"+o.toString()+"'");
        else if (o instanceof Float)
            System.out.println(o.toString()+"f");
        else
            System.out.println(o.toString());
    }
}
Copier après la connexion
modèle de visiteur

peut-il vous aider ? 🎜>Pour implémenter le modèle de visiteur, vous devez créer une interface Visiteur et créer une interface Visitable pour l'objet de collection visité. Ensuite, vous devez créer des classes spécifiques pour implémenter Visiteur et Visitable. Les interfaces sont à peu près les suivantes :

Pour une classe String spécifique, elle peut être implémentée comme suit :

public interface Visitor
{
    public void visitCollection(Collection collection);
    public void visitString(String string);
    public void visitFloat(Float float);
}
public interface Visitable
{
    public void accept(Visitor visitor);
}
Copier après la connexion
Dans la méthode accept, appeler le visiteur selon différents types. méthode correspondante dans :

public class VisitableString implements Visitable
{
    private String value;
    public VisitableString(String string) {
        value = string;
    }
    public void accept(Visitor visitor) {
        visitor.visitString(this);
    }
}
Copier après la connexion

L'implémentation spécifique de Visitor est la suivante :

visitor.visitString(this)

À ce moment-là, tant que la classe VisitableFloat et la classe VisitableCollection sont implémentés et les appels appropriés sont effectués par la méthode visiteur, vous pouvez supprimer la méthode messyPrintCollection qui contient un tas de structures if-else et implémenter la même fonction d'une manière très rafraîchissante. La méthode visitCollection() appelle Visitable.accept(this) , et la méthode accept(). À son tour, la méthode correcte dans le visiteur est appelée. Il s'agit d'une double répartition : le visiteur appelle une méthode dans la classe Visitable, qui à son tour appelle une méthode dans la classe Visiteur. L'instruction if-else a disparu, mais elle introduit toujours beaucoup de code supplémentaire. Vous devez envelopper les objets d'origine, String et Float, dans une classe qui implémente l'interface Visitable. Ce n'est généralement pas un problème. peut restreindre la collection visitée pour qu'elle contienne uniquement des objets visitables. Cependant, cela représente beaucoup de travail supplémentaire. Pire encore, que faites-vous lorsque vous souhaitez ajouter un nouveau type Visitable, tel que VisitableInteger ? Il s’agit là d’un inconvénient majeur du modèle de visiteur. Si vous souhaitez ajouter un nouveau type Visitable, vous devez modifier l'interface Visiteur et chaque classe qui implémente les méthodes de l'interface Visiteur. Vous ne pouvez pas concevoir Visitor comme une interface. Au lieu de cela, vous pouvez concevoir Visitor comme une classe de base abstraite avec

Aucune opération

. Ceci est très similaire à la classe Adapter dans l’interface graphique Java. Le problème avec cela est que vous épuiserez le seul
public class PrintVisitor implements Visitor
{
    public void visitCollection(Collection collection) {
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            Object o = iterator.next();
            if (o instanceof Visitable)
                ((Visitable)o).accept(this);
    }
    public void visitString(String string) {
        System.out.println("'"+string+"'");
    }
    public void visitFloat(Float float) {
        System.out.println(float.toString()+"f");
    }
}
Copier après la connexion
héritage

, et une situation courante est que vous souhaitez également utiliser l'héritage pour implémenter d'autres fonctions, telles que l'héritage de la classe StringWriter. Encore une fois, cela ne peut accéder avec succès qu'aux objets qui implémentent l'interface Visitable.

Heureusement, Java peut rendre votre modèle de visiteur plus flexible, vous pouvez ajouter des objets visitables à votre guise. Comment y parvenir ? La réponse est d’utiliser la réflexion. L'interface réfléchissanteVisitor utilisant la réflexion ne nécessite qu'une seule méthode :

D'accord, ce qui précède est très simple. L'interface Visitable ne sera pas utilisée pour l'instant, j'en reparlerai plus tard. Maintenant, j'implémente la classe PrintVisitor en utilisant la réflexion. Vous n'avez plus besoin d'utiliser la classe wrapper Visitable (qui enveloppe les types primitifs String et Float). Vous pouvez accéder directement à visit() et il appellera la bonne méthode. L’un des avantages de visit() est qu’il distribue la méthode qu’il juge appropriée. Cela n’utilise pas nécessairement la réflexion, cela pourrait utiliser un mécanisme complètement différent.

Dans la nouvelle classe PrintVisitor, il existe des méthodes d'opération correspondant à Collections, String et Float ; pour les types qui ne peuvent pas être traités, elles peuvent être capturées via des instructions catch. Pour les types qui ne peuvent pas être gérés, vous pouvez essayer de gérer toutes leurs superclasses en étendant la méthode visit(). Tout d'abord, ajoutez une nouvelle méthode getMethod(Class c), et la valeur de retour est une méthode qui peut être déclenchée. Il

recherchera toutes les classes parentes et interfaces de la
public interface ReflectiveVisitor {
    public void visit(Object o);
}
Copier après la connexion
Classe c pour trouver une méthode correspondante.

protected Method getMethod(Class c) {
    Class newc = c;
    Method m = null;
    // Try the superclasses
    while (m == null && newc != Object.class) {
        String method = newc.getName();
        method = "visit" + method.substring(method.lastIndexOf('.') + 1);
        try {
            m = getClass().getMethod(method, new Class[] {newc});
        } catch (NoSuchMethodException e) {
            newc = newc.getSuperclass();
        }
    }
    // Try the interfaces.  If necessary, you
    // can sort them first to define 'visitable' interface wins
    // in case an object implements more than one.
    if (newc == Object.class) {
        Class[] interfaces = c.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            String method = interfaces[i].getName();
            method = "visit" + method.substring(method.lastIndexOf(&#39;.&#39;) + 1);
            try {
                m = getClass().getMethod(method, new Class[] {interfaces[i]});
            } catch (NoSuchMethodException e) {}
        }
    }
    if (m == null) {
        try {
            m = thisclass.getMethod("visitObject", new Class[] {Object.class});
        } catch (Exception e) {
            // Can&#39;t happen
        }
    }
    return m;
}
Copier après la connexion

这看上去很复杂,实际上并不。大致来说,首先根据传入的class名称搜索可用方法;如果没找到,就尝试从父类搜索;如果还没找到,就从接口中尝试。最后,(仍没找到)可以使用visitObject()作为默认方法。

由于大家对传统的访问者模式比较熟悉,这里沿用了之前方法命名的惯例。但是,有些人可能注意到,把所有的方法都命名为“visit”并通过参数类型不同来区分,这样更高效。然而,如果你这么做,你必须把visit(Object o)方法的名称改为其他,比如dispatch(Object o)。否则,(当没有对应处理方法时),你无法退回到默认的处理方法,并且当你调用visit(Object o)方法时,为了确保正确的方法调用,你必须将参数强制转化为Object。

为了利用getMethod()方法,现在需要修改一下visit()方法。

public void visit(Object object) {
    try {
        Method method = getMethod(getClass(), object.getClass());
        method.invoke(this, new Object[] {object});
    } catch (Exception e) { }
}
Copier après la connexion

现在,visitor类更加强大了——可以传入任意的对象并且有对应的处理方法。另外,有一个默认处理方法,visitObject(Object o),的好处就是就可以捕捉到任何没有明确说明的类型。再稍微修改下,你甚至可以添加一个visitNull()方法。

我仍保留Visitable接口是有原因的。传统访问者模式的另一个好处是它可以通过Visitable对象控制对象结构的遍历顺序。举例来说,假如有一个实现了Visitable接口的类TreeNode,它在accept()方法中遍历自己的左右节点。

public void accept(Visitor visitor) {
    visitor.visitTreeNode(this);
    visitor.visitTreeNode(leftsubtree);
    visitor.visitTreeNode(rightsubtree);
}
Copier après la connexion

这样,只要修改下Visitor类,就可以通过Visitable类控制遍历:

public void visit(Object object) throws Exception
{
    Method method = getMethod(getClass(), object.getClass());
    method.invoke(this, new Object[] {object});
    if (object instanceof Visitable)
    {
        callAccept((Visitable) object);
    }
}
public void callAccept(Visitable visitable) {
    visitable.accept(this);
}
Copier après la connexion

如果你实现了Visitable对象的结构,你可以保持callAccept()不变,就可以使用Visitable控制的对象遍历。如果你想在visitor中遍历对象结构,你只需重写allAccept()方法,让它什么都不做。

当使用几个不同的visitor去操作同一个对象集合时,访问者模式的力量就会展现出来。比如,当前有一个解释器、中序遍历器、后续遍历器、XML编写器以及SQL编写器,它们可以处理同一个对象集合。我可以轻松地为这个集合再写一个先序遍历器或者一个SOAP编写器。另外,它们可以很好地兼容它们不识别的类型,或者我愿意的话可以让它们抛出异常。

总结

使用Java反射,可以使访问者模式提供一种更加强大的方式操作对象结构,可以按照需求灵活地增加新的Visitable类型。我希望在你的编程之旅中可以使用访问者模式。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Vous avez un jeu croisé?
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Nombre parfait en Java Nombre parfait en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Weka en Java Weka en Java Aug 30, 2024 pm 04:28 PM

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Numéro de Smith en Java Numéro de Smith en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Questions d'entretien chez Java Spring Questions d'entretien chez Java Spring Aug 30, 2024 pm 04:29 PM

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Break or Return of Java 8 Stream Forach? Break or Return of Java 8 Stream Forach? Feb 07, 2025 pm 12:09 PM

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Horodatage à ce jour en Java Horodatage à ce jour en Java Aug 30, 2024 pm 04:28 PM

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.

Programme Java pour trouver le volume de la capsule Programme Java pour trouver le volume de la capsule Feb 07, 2025 am 11:37 AM

Les capsules sont des figures géométriques tridimensionnelles, composées d'un cylindre et d'un hémisphère aux deux extrémités. Le volume de la capsule peut être calculé en ajoutant le volume du cylindre et le volume de l'hémisphère aux deux extrémités. Ce tutoriel discutera de la façon de calculer le volume d'une capsule donnée en Java en utilisant différentes méthodes. Formule de volume de capsule La formule du volume de la capsule est la suivante: Volume de capsule = volume cylindrique volume de deux hémisphères volume dans, R: Le rayon de l'hémisphère. H: La hauteur du cylindre (à l'exclusion de l'hémisphère). Exemple 1 entrer Rayon = 5 unités Hauteur = 10 unités Sortir Volume = 1570,8 unités cubes expliquer Calculer le volume à l'aide de la formule: Volume = π × r2 × h (4

Comment exécuter votre première application Spring Boot dans Spring Tool Suite? Comment exécuter votre première application Spring Boot dans Spring Tool Suite? Feb 07, 2025 pm 12:11 PM

Spring Boot simplifie la création d'applications Java robustes, évolutives et prêtes à la production, révolutionnant le développement de Java. Son approche "Convention sur la configuration", inhérente à l'écosystème de ressort, minimise la configuration manuelle, allo

See all articles