共计 3651 个字符,预计需要花费 10 分钟才能阅读完成。
导读 | 大多数情况下你不需要访问者模式,但当一旦需要访问者模式时,那就是真的需要它了,这是设计模式创始人的原话。可以看出应用场景比较少,但需要它的时候是不可或缺的,这篇文章就开始学习最后一个设计模式——访问者模式 |
编程是一门艺术,大批量的改动显然是非常丑陋的做法,用心的琢磨写的代码让它变的更美观。
在生活中,电影或电视剧中的人物角色,不同的观众对他们的评价也不同;还有顾客在商场购物时放在“购物车”中的商品,顾客主要关心所选商品的性价比,而收银员关心的是商品的价格和数量。
这些被处理的数据元素相对稳定而访问方式多种多样的数据结构,如果用“访问者模式”来处理比较方便。访问者模式能把处理方法从数据结构中分离出来,并可以根据需要增加新的处理方法,且不用修改原来的程序代码与数据结构,这提高了程序的扩展性和灵活性。
访问者(Visitor)模式:是将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
访问者设计模式主要解决:java 多态方法重载的静态化问题。
访问者(Visitor)模式是一种对象行为型模式,其主要优点:
访问者(Visitor)模式的不足:
访问者(Visitor)模式实现的关键是如何将作用于元素的操作分离出来封装成独立的类
访问者模式包含以下主要角色。
场景介绍:统计不同水果的价格,不同的水果放置到不同的集合,但是由于 java 多态中方法重载是静态化的不足,导致统计不出来价格,就可以使用访问者设计模式来处理。
public interface Fruit {int price();
void draw();
int accept(Visit visit);
}
public class Apple implements Fruit {
private int price = 100;
public Apple(){}
public Apple(int price){this.price = price;}
public void pack(AppleBag bag){bag.pack();
}
@Override
public int price() {return price;}
@Override
public void draw() {System.out.print("苹果红富士");
}
public void setPrice(int price) {this.price = price;}
public int accept(Visit visit){
/* 指针可以传递真实类型 */
return visit.sell(this);
}
}
public class Banana implements Fruit {
private int price = 60;
@Override
public int price() {return price;}
public void pack(BananaBag bag){bag.pack();
}
@Override
public void draw() {System.out.print("仙人蕉");
}
public int accept(Visit visit){return visit.sell(this);
}
public void setPrice(int price) {this.price = price;}
}
public class Orange implements Fruit {
private String name = "";
private int price = 70;
public Orange(String name,int price){
this.price = price;
this.name = name;
}
public void pack(OrangeBag bag){bag.pack();
}
@Override
public int price() {return price;}
@Override
public void draw() {System.out.print("砂糖桔");
}
public int accept(Visit visit){return visit.sell(this);
}
public void setPrice(int price) {this.price = price;}
}
public class Visit {
/* 苹果计价 */
public int sell(Apple apple){System.out.println("apple's price: ¥50");
return 50;
}
/* 桔子计价 */
public int sell(Orange orange){System.out.println("orange's price: ¥20");
return 20;
}
/* 香蕉计价 */
public int sell(Banana banana){System.out.println("banana's price: ¥30");
return 30;
}
// 其它水果计价
public int sell(Fruit fruit){System.out.println("other price: ¥10");
return 10;
}
}
public class VisitClient {private static Visit visit = new Visit();
/* 库存 */
private static List list = new ArrayList();
static {list.add(StaticFactory.getFruitApple());
list.add(StaticFactory.getFruitOrange());
list.add(StaticFactory.getFruitBanana());
list.add(StaticFactory.getFruitApple());
list.add(StaticFactory.getFruitOrange());
}
private static int price() {
int total = 0;
for (Fruit fruit : list) {total += fruit.accept(visit);
}
System.out.println("总价值:" + total);
return total;
}
public static void main(String[] args) {price();
}
访问者设计模式的关键是:不能直接使用 visit 对象直接调用 sell 方法将水果对象传递进去,因为直接传递进去由于方法重载的静态化问题,不会执行相应的方法,需要是使用 fruit 的 accept 方法才行。
通常在以下情况可以考虑使用访问者(Visitor)模式。