Design Pattern Learning Summary 01----Visitor Pattern

           Scenes

        Description: Visitors are changeable, the structure in the computer (the data structure remains unchanged), and the operation does not affect the internal structure of the computer;

1.      The ledger has fixed expenses and income; 

            The boss checks the total expenditure and total income of the ledger

            Accountant Check whether the income in the ledger is taxable when it is salary;

        Usage summary : The internal data composition of the ledger remains the same, expenses and income; according to the visitor's boss, the accountant, the behavior of the two of them - the purpose and behavior of viewing the ledger is different. Viewing the contents of the ledger without changing it is easy to add another visitor;

    2. The computer has fixed structural elements such as mouse and keyboard;

        Different users access the computer to do different things, but do not change the structure and elements of the computer;

        accomplish:

(1) Visitor: interface or abstract class, which defines the behavior of accessing each element (Element), its parameters are the elements that can be accessed, and the number of its methods is theoretically the same as the number of elements, therefore, The visitor pattern requires the element class family to be stable. If element classes are frequently added and removed, the Visitor interface will be frequently modified. If this is the case, the visitor pattern is not suitable.

(2) ConcreteVisitor1, ConcreteVisitor2: specific access classes, which need to give the specific behaviors generated when each element class is accessed.

(3) Element: Element interface or abstract class, which defines a method for accepting visitors (Accept), which means that each element must be accessible by the visitor.

(4) ConcreteElementA, ConcreteElementB: Concrete element classes, which provide a concrete implementation of the receiving access method, and this concrete implementation usually uses the method provided by the visitor to access the element class.

(5) ObjectStructure: The object structure mentioned in the definition. The object structure is an abstract representation that internally manages a collection of elements, and these elements can be iterated for visitors to access.

Simple example of visitor pattern

We all know that finance has a ledger, and this ledger can be used as an object structure, and there are two elements in it, income and expenditure, which meet the requirements of our visitor model, that is, the number of elements is stable, Because the elements in the ledger can only be income and expenses.

There may be several types of people who view the ledger, such as the boss, the accountant of the accounting firm, the treasurer, and so on. And these people obviously have different purposes and behaviors when they look at the ledger.

First we give the interface of the monad, which has only one method accept.

//单个单子的接口(相当于Element)
public interface Bill {

    void accept(AccountBookViewer viewer);

}
  • 1

The method parameter AccountBookViewer is an account book visitor interface, and the next is the implementation class, the income list and the consumption list, or the income and expenditure class.

//消费的单子
public class ConsumeBill implements Bill{

    private double amount;

    private String item;

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

    public void accept(AccountBookViewer viewer) {
        viewer.view(this);
    }

    public double getAmount() {
        return amount;
    }

    public String getItem() {
        return item;
    }

}
//收入单子
public class IncomeBill implements Bill{

    private double amount;

    private String item;

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

    public void accept(AccountBookViewer viewer) {
        viewer.view(this);
    }

    public double getAmount() {
        return amount;
    }

    public String getItem() {
        return item;
    }

}
  • 1

The most important thing above is the accept method inside, which directly allows the visitor to access itself, which is equivalent to a static dispatch (explained at the end of the article). Of course, we can also directly give the method a different name without using overloading.

Next is the ledger visitor interface

//账单查看者接口(相当于Visitor)
public interface AccountBookViewer {

    //查看消费的单子
    void view(ConsumeBill bill);

    //查看收入的单子
    void view(IncomeBill bill);

}
  • 1

These two methods are overloaded methods, which are used in the above element classes. Of course, you can also do it in the same way as in the visitor mode class diagram. Name the two methods viewConsumeBill and viewIncomeBill respectively, and the general recommendation According to the class diagram

Visitor implementation

//老板类,查看账本的类之一
public class Boss implements AccountBookViewer{

    private double totalIncome;

    private double totalConsume;

    //老板只关注一共花了多少钱以及一共收入多少钱,其余并不关心
    public void view(ConsumeBill bill) {
        totalConsume += bill.getAmount();
    }

    public void view(IncomeBill bill) {
        totalIncome += bill.getAmount();
    }

    public double getTotalIncome() {
        System.out.println("老板查看一共收入多少,数目是:" + totalIncome);
        return totalIncome;
    }

    public double getTotalConsume() {
        System.out.println("老板查看一共花费多少,数目是:" + totalConsume);
        return totalConsume;
    }

}
  • 1
//注册会计师类,查看账本的类之一
public class CPA implements AccountBookViewer{

    //注会在看账本时,如果是支出,则如果支出是工资,则需要看应该交的税交了没
    public void view(ConsumeBill bill) {
        if (bill.getItem().equals("工资")) {
            System.out.println("注会查看工资是否交个人所得税。");
        }
    }
    //如果是收入,则所有的收入都要交税
    public void view(IncomeBill bill) {
        System.out.println("注会查看收入交税了没。");
    }

}
  • 1

The boss only cares about the total amount of income and expenses, and the bet will only pay attention to whether the taxpayer pays tax

Next is the ledger class, which is the object structure in the current visitor pattern example

//账本类(相当于ObjectStruture)
public class AccountBook {
    //单子列表
    private List<Bill> billList = new ArrayList<Bill>();
    //添加单子
    public void addBill(Bill bill){
        billList.add(bill);
    }
    //供账本的查看者查看账本
    public void show(AccountBookViewer viewer){
        for (Bill bill : billList) {
            bill.accept(viewer);
        }
    }
}
  • 1

There is a list in the ledger class. This list is a collection of elements (Bill), which is the usual representation of the object structure. It is generally a collection of elements, but this collection is not necessarily a list, but may also be a tree or a linked list. And so on any data structure, even several data structures. The show method is the essence of the ledger class, it will enumerate each element for visitors to access.

test client

public class Client {

    public static void main(String[] args) {
        AccountBook accountBook = new AccountBook();
        //添加两条收入
        accountBook.addBill(new IncomeBill(10000, "卖商品"));
        accountBook.addBill(new IncomeBill(12000, "卖广告位"));
        //添加两条支出
        accountBook.addBill(new ConsumeBill(1000, "工资"));
        accountBook.addBill(new ConsumeBill(2000, "材料费"));

        AccountBookViewer boss = new Boss();
        AccountBookViewer cpa = new CPA();

        //两个访问者分别访问账本
        accountBook.show(cpa);
        accountBook.show(boss);

        ((Boss) boss).getTotalConsume();
        ((Boss) boss).getTotalIncome();
    }
}
  • 1

In the above code, it can be understood that the ledger and the elements in the ledger are very stable, these are almost impossible to change, and the part of the visitor is the easiest to change.

The biggest advantage of the visitor pattern is that it is very easy to add visitors. From the code point of view, if you want to add a visitor, you only need to do one thing, that is, write a class that implements the AccountBookViewer interface, and then you can directly Call the show method of AccountBook to access the ledger.

如果没使用访问者模式,一定会增加许多if else,而且每增加一个访问者,你都需要改你的if else,代码会显得非常臃肿,而且非常难以扩展和维护。




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324822624&siteId=291194637