[设计模式]访问者模式

设计模式之访问者模式

1.参考了这边文章,个人觉得访问者模式不是非常适用,它提高了代码复杂度,而且对容器和访问业务两边都有入侵行为(通过接口)。对于单一访问者的需求,直接对容器进行遍历操作可能更好,或者直接在容器上提供方法,而不是给访问者提供接口。在需要使用多个访问者且容器的元素基本不变的情况下,访问者模式才是比较适用的。

2.Java 8 Stream 流特性是依据访问者模式实现的。

3.以下是个人学习时写的一个例子:

1.接口一:抽象访问者行为:

package com.xdsux.java.visitor;

public interface InfoViewer {
    void view(ManVIP vipInfo);
    
    void view(WomanVIP vipInfo);
}

因为容器的元素有两种,针对两种元素有不同的行为,所有有方法重载。

2.接口二:抽象元素提供访问者信息的行为。

package com.xdsux.java.visitor;

public interface VIPInfo {
    //元素需要继承的接口,向访问者展示信息
    void showInfo(InfoViewer viewer);
}

容器中的元素实现该接口,访问者作为参数传入,元素将自身信息暴露给访问者(项目开发中,这里元素的信息对外暴露了,并不安全,当然也可以再次之上进一步优化):

package com.xdsux.java.visitor;

public class ManVIP implements VIPInfo {
    
    private int age;
    private int income;
    
    public ManVIP(int age, int income) {
        this.age = age;
        this.income = income;
    }

    @Override
    public void showInfo(InfoViewer viewer) {
        // TODO Auto-generated method stub
        viewer.view(this);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getIncome() {
        return income;
    }

    public void setIncome(int income) {
        this.income = income;
    }

}

WomenVIP.java代码和ManVIP.java一样。

3.容器类,容纳元素,并提供让访问者遍历元素的方法:

package com.xdsux.java.visitor;

import java.util.ArrayList;
import java.util.List;

public class InfoCenter {
    private List<VIPInfo> ls = new ArrayList<>();
    
    //用于加入会员信息
    public void add(VIPInfo vip) {
        this.ls.add(vip);
    }
    
    //向访问者提供会员信息
    public void show(InfoViewer viewer) {
        for(VIPInfo vip : ls) {
            //每个元素展示自己的信息
            vip.showInfo(viewer);
        }
    }

}

 4.访问者实现类:VisitorA 实现访问者接口。

 定义访问元素时的行为,如果有不同的访问行为,可以定义多个访问者类。

package com.xdsux.java.visitor;

public class VisitorA implements InfoViewer {
    
    private int countsMan;
    private int countsWoman;
    
    private int sumAge;
    private int sumIncome;

    @Override
    public void view(ManVIP vipInfo) {
        //visitor只关心男会员的收入
        this.sumIncome += vipInfo.getIncome();
        this.countsMan++;
    }

    @Override
    public void view(WomanVIP vipInfo) {
        //visitor只关心女会员的年龄
        this.sumAge += vipInfo.getAge();
        this.countsWoman++;
    }
    
    public void showVisitorInfo() {
        System.out.println("男会员总人数: " + this.countsMan);
        System.out.println("平均收入: " + this.sumIncome/this.countsMan);
        System.out.println("女会员总人数: " + this.countsWoman);
        System.out.println("平均年龄: " + this.sumAge/this.countsWoman);
    }

}

测试:

package com.xdsux.java.visitor;

public class Client {

    public static void main(String[] args) {
        
        //创建容器类实例
        InfoCenter ic = new InfoCenter();
        
        //在容器中载入不同元素
        ic.add(new ManVIP(32, 17000));
        ic.add(new ManVIP(32, 18000));
        ic.add(new ManVIP(32, 20000));
        
        ic.add(new WomanVIP(32, 17000));
        ic.add(new WomanVIP(22, 17000));
        ic.add(new WomanVIP(27, 17000));
        ic.add(new WomanVIP(26, 17000));
        
        //创建访问者
        VisitorA va = new VisitorA();
        
        //访问者访问容器实例下的元素。并执行各自的操作
        ic.show(va);
        
        va.showVisitorInfo();
        
    }

}

输出:

男会员总人数: 3
平均收入: 18333
女会员总人数: 4
平均年龄: 26
原文地址:https://www.cnblogs.com/xdsux/p/9669467.html