设计模式之-访问者模式(Visitor Design Pattern)

访问者模式行为的设计模式之一。访问者模式使用时,咱们必须是对一组相似种类对象统一操做。访问者模式的帮助下,咱们能够转移这套逻辑到另外一个类进行操做

例如,考虑一个购物,咱们能够添加不一样类型的项目元素咱们点击结账按钮,就计算要支付的总金额。如今,咱们能够在项目计算逻辑,或者咱们能够使用访问者模式这个逻辑移动到另外一个类上使用这套访问模式。让咱们来实现这个访问者模式的例子。

为了实现访问者模式,首先,咱们将建立不一样类型的项目元素购物车中使用

java


ItemElement.java设计模式

package com.journaldev.design.visitor;
 
public interface ItemElement {
 
    public int accept(ShoppingCartVisitor visitor);
}

请注意,accept方法参数设置咱们能够有一些其余的方法,但为了简单起见,我不打算那么多细节,只注重访问者模式让咱们建立一些具体的不一样类型的项目

Book.javabash

package com.journaldev.design.visitor;
 
public class Book implements ItemElement {
 
    private int price;
    private String isbnNumber;
     
    public Book(int cost, String isbn){
        this.price=cost;
        this.isbnNumber=isbn;
    }
     
    public int getPrice() {
        return price;
    }
 
    public String getIsbnNumber() {
        return isbnNumber;
    }
 
    @Override
    public int accept(ShoppingCartVisitor visitor) {
        return visitor.visit(this);
    }
 
}

Fruit.javaapp

package com.journaldev.design.visitor;
 
public class Fruit implements ItemElement {
     
    private int pricePerKg;
    private int weight;
    private String name;
     
    public Fruit(int priceKg, int wt, String nm){
        this.pricePerKg=priceKg;
        this.weight=wt;
        this.name = nm;
    }
     
    public int getPricePerKg() {
        return pricePerKg;
    }
 
 
    public int getWeight() {
        return weight;
    }
 
    public String getName(){
        return this.name;
    }
     
    @Override
    public int accept(ShoppingCartVisitor visitor) {
        return visitor.visit(this);
    }
 
}

注意accept()方法具体的类的实现对其调用Visitor    visit()方法是,将自身做为参数传递
咱们可使visit()方法不一样类型的items,由实现Visitor接口具体的类去实现

ShoppingCartVisitor.javaide

package com.journaldev.design.visitor;
 
public interface ShoppingCartVisitor {
 
    int visit(Book book);
    int visit(Fruit fruit);
}

如今咱们实现 visitor接口,每一种item会有本身计算方法测试

ShoppingCartVisitorImpl.javaui

package com.journaldev.design.visitor;
 
public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {
 
    @Override
    public int visit(Book book) {
        int cost=0;
        //apply 5$ discount if book price is greater than 50
        if(book.getPrice() > 50){
            cost = book.getPrice()-5;
        }else cost = book.getPrice();
        System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);
        return cost;
    }
 
    @Override
    public int visit(Fruit fruit) {
        int cost = fruit.getPricePerKg()*fruit.getWeight();
        System.out.println(fruit.getName() + " cost = "+cost);
        return cost;
    }
 
}

测试程序:

ShoppingCartClient.javathis

package com.journaldev.design.visitor;
 
public class ShoppingCartClient {
 
    public static void main(String[] args) {
        ItemElement[] items = new ItemElement[]{new Book(20, "1234"),new Book(100, "5678"),
                new Fruit(10, 2, "Banana"), new Fruit(5, 5, "Apple")};
         
        int total = calculatePrice(items);
        System.out.println("Total Cost = "+total);
    }
 
    private static int calculatePrice(ItemElement[] items) {
        ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
        int sum=0;
        for(ItemElement item : items){
            sum = sum + item.accept(visitor);
        }
        return sum;
    }
 
}

输出结果:

Book ISBN::1234 cost =20
Book ISBN::5678 cost =95
Banana cost = 20
Apple cost = 25
Total Cost = 160


请注意,若是执行accept()方法中的全部项目都是相同的,但也能够是不一样的,例如能够有逻辑检查项目是免费的,那么请不要调用visit()方法的。
spa

Visitor Pattern Class Diagram:


总结:设计

这种模式的好处是,若是操做的逻辑改变了那么咱们就须要作出改变在访问者实现,而不是作在全部的项目类别
另外一个好处是,增长一个新的项目,对于系统很容易实现,只须要implements访问者的接口和实现便可,对于现有的项目类别将不会受到影响
访问者模式缺点:咱们必须知道visit()方法的返回值类型才能够这样设计,否则咱们将不得不改变界面全部的实现。另外一个缺点是,若是数量太多的visitor接口实现项目将很难扩展

相关文章
相关标签/搜索