• [设计模式]访问者模式


    设计模式之访问者模式

    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
  • 相关阅读:
    python中xlrd模块
    2021, 8, 26模拟赛
    2021, 8,24 模拟赛
    每天挂 0 的小技巧
    2021,8,23 模拟赛
    异常处理
    64位 windows10,MYSQL8.0.13重置密码(忘记密码或者无法登录)
    Android仓库
    学习笔记索引
    「学习笔记」各类容斥反演总结
  • 原文地址:https://www.cnblogs.com/xdsux/p/9669467.html
Copyright © 2020-2023  润新知