• 设计模式-访问者模式(Visitor)


    访问者模式是行为模式的一种。访问者模式的基本想法是,软件系统中拥有一个由许多对象构成的、比较稳定的对象结构,这些对象的类都拥有一个accept方法用来接受访问者的访问。访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素做不同的处理。

    角色和职责:

    1.访问者(Visitor):

       访问不同的Concrete Element

    2.具体访问者(Concrete Visitor)-Boss、CPA:

        具体的访问类,它需要给出对每一个元素类访问时所产生的具体行为

    3.元素接口(Element)-Bill:

      元素接口或者抽象类,它定义了一个接受访问者的方法(Accept),其意义是指每一个元素都要可以被访问者访问

    4.具体元素类(ConcreteElement)-ConcreteElementA、ConcreteElementB:

       具体的元素类,它提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法

    5.对象结构(ObjectStructure)-AccountBook:

      定义当中所说的对象结构,对象结构是一个抽象表述,它内部管理了元素集合,并且可以迭代这些元素供访问者访问。

    UML图:

    具体代码:

    /**
     * 访问者
     */
    public interface Visitor {
        void visitor(ConsumeBill consumeBill);//消费情况
        void visitor(IncomeBill incomeBill);//收入情况
    }
    /**
     * 访问者:老板
     */
    public class Boss implements Visitor{
        private Double totalConsumeMoney = 0d;//消费总金额
        private Double totalIncomeMoney = 0d;//收入总金额
        @Override
        public void visitor(ConsumeBill consumeBill) {
            totalConsumeMoney += consumeBill.getMoney();
        }
    
        @Override
        public void visitor(IncomeBill incomeBill) {
            totalIncomeMoney += incomeBill.getMoney();
        }
    
        public void display(){
            System.out.println("总收入:"+this.totalIncomeMoney+",总消费:"+this.totalConsumeMoney);
        }
    }
    /**
     * 访问者:会计访问,做操作
     */
    public class CPA implements Visitor{
        @Override
        public void visitor(ConsumeBill consumeBill) {
            if(consumeBill.getType().equalsIgnoreCase("工资")){//公司消费工资,也是要给税的
                System.out.println("发工资"+consumeBill.getMoney()+"元,交税");
            }
        }
    
        @Override
        public void visitor(IncomeBill incomeBill) {
            //会计做账,每一笔收入要给税
            System.out.println(incomeBill.getType()+",收入金额:"+incomeBill.getMoney()+"元,"+"交税");
        }
    }
    /**
     * element :元素接口
     */
    public interface Bill {
        void accept(Visitor visitor);
    }
    /**
     * 消费情况
     */
    public class ConsumeBill implements Bill{
        private Double money;//消费金额
        private String type;//消费类型
        public ConsumeBill(Double money,String type){
            this.money = money;
            this.type = type;
        }
    
        @Override
        public void accept(Visitor visitor) {
            visitor.visitor(this);
        }
    
        public Double getMoney() {
            return money;
        }
    
        public String getType() {
            return type;
        }
    
    }
    /**
     * 收入情况
     */
    public class IncomeBill implements Bill{
        private Double money;//收入金额
        private String type;//收入类型
        public IncomeBill(Double money,String type){
            this.money = money;
            this.type = type;
        }
    
        @Override
        public void accept(Visitor visitor) {
            visitor.visitor(this);
        }
    
        public Double getMoney() {
            return money;
        }
    
        public String getType() {
            return type;
        }
    }
    /**
     * 对象结构: 帐簿
     */
    public class AccountBook {
        private List<Bill> list = new ArrayList<Bill>();
    
        /**
         * 添加流水
         * @param bill
         */
        public void add(Bill bill){
            list.add(bill);
        }
    
        /**
         * 供账本的查看者查看账本
         * @param visitor
         */
        public void show(Visitor visitor){
            for(Bill bill:list){
                bill.accept(visitor);
            }
        }
    }
    public class Main {
        public static void main(String[] args) {
            //添加消费记录
            ConsumeBill consumeBillCloth = new ConsumeBill(23.24,"进购打印机");
            ConsumeBill consumeBillShoes = new ConsumeBill(212.99,"进购桌子");
            ConsumeBill consumeBillSalary = new ConsumeBill(3000.00,"工资");
            IncomeBill incomeBillAlipay = new IncomeBill(300.66,"卖维护");
            IncomeBill incomeBillWechat = new IncomeBill(123.88,"卖软件");
    
            //帐蒲
            AccountBook accountBook = new AccountBook();
            accountBook.add(consumeBillCloth);
            accountBook.add(consumeBillShoes);
            accountBook.add(consumeBillSalary);
            accountBook.add(incomeBillAlipay);
            accountBook.add(incomeBillWechat);
    
            //老板过来访问
            Boss boss = new Boss();
            accountBook.show(boss);
            boss.display();
            System.out.println("-------------------");
    
            //会计过来访问
            CPA cpa = new CPA();
            accountBook.show(cpa);
        }
    }

    结果:

    总收入:424.54,总消费:3236.23
    -------------------
    发工资3000.0元,交税
    卖维护,收入金额:300.66元,交税
    卖软件,收入金额:123.88元,交税

    使用场景
    (1)对象结构比较稳定,但经常需要在此对象结构上定义新的操作。

    (2)需要对一个对象结构中的对象进行很多不同的且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。

    源码地址:https://github.com/qjm201000/design_pattern_visitor.git

  • 相关阅读:
    HDU1026 Ignatius and the Princess I
    luogu_1865 A % B Problem
    luogu_1092 虫食算
    luogu_1111 修复公路
    luogu_1265 公路修建
    luogu_2330 [SCOI2005]繁忙的都市
    luogu_1613 跑路
    luogu_3386 【模板】二分图匹配
    luogu_3388 【模板】割点(割顶)
    luogu_2327 扫雷
  • 原文地址:https://www.cnblogs.com/qjm201000/p/10133383.html
Copyright © 2020-2023  润新知