ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式18 - 访问者模式【Visitor Pattern】

2021-07-07 17:51:57  阅读:168  来源: 互联网

标签:Pattern void AccountBookView item amount Visitor 设计模式 public 访问者


访问者模式

定义:

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

举例:(记账例子):
账本只有收入和消费类型,而访问者有多种,如老板和会计。

/**
 * 账单接口,有接受访问者的功能
 */
interface Bill {
    void accept(AccountBookView viewer);
}

/**
*消费账单
*/
class ConsumerBill implements Bill {
    private String item;
    private double amount;

    public ConsumerBill(String item, double amount) {
        this.item = item;
        this.amount = amount;
    }

    @Override
    public void accept(AccountBookView viewer) {
        viewer.view(this);
    }

    public String getItem() {
        return item;
    }

    public double getAmount() {
        return amount;
    }
}

/*
*支出账单
*/
class IncomingBill implements Bill {
    private String item;
    private double amount;

    public IncomingBill(String item, double amount) {
        this.item = item;
        this.amount = amount;
    }

    @Override
    public void accept(AccountBookView viewer) {
        viewer.view(this);
    }

    public String getItem() {
        return item;
    }

    public double getAmount() {
        return amount;
    }
}


/**
*访问者接口
*/
interface AccountBookView {
    //查看消费的单子
    void view(ConsumerBill consumerBill);

    //查看收入单子
    void view(IncomingBill incomingBill);
}


/**
*访问者老板
*/
class Boss implements AccountBookView {

    private double totalConsumer;
    private double totalIncome;


    @Override
    public void view(ConsumerBill consumerBill) {
        totalConsumer = totalConsumer + consumerBill.getAmount();
    }

    @Override
    public void view(IncomingBill incomingBill) {
        totalIncome = totalIncome + incomingBill.getAmount();
    }

    public void getTotalConsumer() {
        System.out.println("老板一共消费了" + totalConsumer);
    }

    public void getTotalIncome() {
        System.out.println("老板一共收入了" + totalIncome);
    }

}

/**
*访问者会计
*/
class CPA implements AccountBookView {

    int count = 0;

    // 查看消费的单子
    public void view(ConsumerBill consumerBill) {
        count++;
        if (consumerBill.getItem().equals("消费")) {
                    System.out.println("第" + count + "个单子消费了:" + consumerBill.getAmount());
        }
    }

    // 查看收入单子

    public void view(IncomingBill incomeBill) {

        if (incomeBill.getItem().equals("收入")) {
            System.out.println("第" + count + "个单子收入了:" + incomeBill.getAmount());
        }
    }

}

/**
*账单类:用于添加账单,和为每一个账单添加访问者
*/
class AccountBook {

    private List<Bill> listBill = new ArrayList<Bill>();

    // 添加单子
    public void add(Bill bill) {
        listBill.add(bill);
    }

    // 为每个账单添加访问者
    public void show(AccountBookView viewer) {
        for (Bill b : listBill) {
            b.accept(viewer);
        }
    }
}
/**
* 客户端
*/
public class Client{

    public void main(String[] args) {

        // 创建消费和收入单子
        Bill consumerBill = new ConsumerBill("消费", 3000);
        Bill incomeBill = new IncomingBill("收入", 5000);
        Bill consumerBill2 = new ConsumerBill("消费", 4000);
        Bill incomeBill2 = new IncomingBill("收入", 8000);

        // 添加单子
        AccountBook accountBook = new AccountBook();
        accountBook.add(consumerBill);
        accountBook.add(incomeBill);
        accountBook.add(consumerBill2);
        accountBook.add(incomeBill2);

        // 创建访问者
        AccountBookView boss = new Boss();
        AccountBookView cpa = new CPA();

        // 接受访问者
        accountBook.show(boss);
        accountBook.show(cpa);

        // boss查看总收入和总消费
        ((Boss) boss).getTotalConsumer();
        ((Boss) boss).getTotalIncome();
    }
}

总结:

意图:主要将数据结构与数据操作分离。

主要解决:稳定的数据结构和易变的操作耦合问题。

何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,使用访问者模式将这些封装到类中。

如何解决:在被访问的类里面加一个对外提供接待访问者的接口。

关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

使用场景:
1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,也不希望在增加新操作时修改这些类。

注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

 

标签:Pattern,void,AccountBookView,item,amount,Visitor,设计模式,public,访问者
来源: https://blog.51cto.com/u_15294985/3006174

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有