设计模式 之 访问者模式
概念
核心理念:将数据结构与算法分离。
使用场景:数据结构不变动,算法经常变动。
- 1、一个Visitor类存放被访问的对象,访问者主要处理具体算法与行为。
// 访问者public interface Visitor { // Subject 是被访问的对象 public void visit(Subject sub); }/** 具体访问者处理具体算法 */
- 2、被访问的对象,也就是数据结构。
// 被访问的对象public interface Subject { // 接收访问者访问 public void accept(Visitor visitor); } // 具体实现public class MySubject implements Subject { @Override public void accept(Visitor visitor) { // 让访问者访问自己 visitor.visit(this); } }
代码场景
不同的顾客对商品持有不同的意见。 顾客A、顾客B买衣服裤子,商店上架各种衣服和裤子。
代码
Goods
/** * 商品抽象类 * @author GaoYuan * @date 2018/11/11 上午8:38 */public abstract class Goods { /** 商品名字 */ public String goodsName; /** 商品价格 */ public int price; public void setGoodsName(String goodsName){ this.goodsName = goodsName; } public void setPrice(int price){ this.price = price; } /** 接收访问的方法 */ public abstract void accept(Visitor visitor);}
上衣
/** * 衣服 * @author GaoYuan * @date 2018/11/11 上午8:41 */public class Clothes extends Goods{ /** 颜色 */ private String color; public Clothes(String goodsName, int price, String color){ setGoodsName(goodsName); setPrice(price); this.color = color; } public String getColor() { return color; } @Override public void accept(Visitor visitor) { visitor.visit(this); }}
裤子
/** * 裤子 * @author GaoYuan * @date 2018/11/11 上午8:41 */public class Trousers extends Goods{ /** 长度 */ private int length; public Trousers(String goodsName, int price, int length){ setGoodsName(goodsName); setPrice(price); this.length = length; } public int getLength() { return length; } @Override public void accept(Visitor visitor) { visitor.visit(this); }}
管理所有商品对象
/** * 店面 * @author GaoYuan * @date 2018/11/11 上午8:53 */public class Shop { private ListgoodsList = new ArrayList<>(); /** 添加 */ public void add(Goods goods){ goodsList.add(goods); } /** 商家询问顾客看中哪件 */ public void askAnswer(Visitor visitor){ for(Goods goods:goodsList){ // 商品挨个接收访问者访问 goods.accept(visitor); } }}
访问者接口
/** * 访问者接口 * @author GaoYuan * @date 2018/11/11 上午8:33 */public interface Visitor { /** 访问商品 */ void visit(Goods goods);}
具体访问者
/** * 男生买衣服裤子 * @author GaoYuan * @date 2018/11/11 上午8:50 */public class ManVisitor implements Visitor{ @Override public void visit(Goods goods) { if(goods instanceof Clothes){ if(((Clothes)goods).price > 100){ System.out.println("[ManVisitor]->" + ((Clothes)goods).goodsName + ":太贵了,不买"); }else if("red".equals(((Clothes)goods).getColor())){ System.out.println("[ManVisitor]->" + ((Clothes)goods).goodsName + ":红色太丑了,不买"); }else{ System.out.println("[ManVisitor]->" + ((Clothes)goods).goodsName + ":价格颜色都能接收,买了"); } }else if(goods instanceof Trousers){ if(((Trousers)goods).price > 100){ System.out.println("[ManVisitor]->" + ((Trousers)goods).goodsName + ":太贵了,不买"); }else if(((Trousers)goods).getLength() > 20){ System.out.println("[ManVisitor]->" + ((Trousers)goods).goodsName + ":太长了,不买"); }else if(((Trousers)goods).getLength() < 10){ System.out.println("[ManVisitor]->" + ((Trousers)goods).goodsName + ":太短了,不买"); }else{ System.out.println("[ManVisitor]->" + ((Trousers)goods).goodsName + ":价格长度都合适,买了"); } } }}/** * 女生买衣服裤子 * @author GaoYuan * @date 2018/11/11 上午8:50 */public class WomanVisitor implements Visitor{ @Override public void visit(Goods goods) { if(goods instanceof Clothes){ if(((Clothes)goods).price > 500){ System.out.println("[WomanVisitor]->" + ((Clothes)goods).goodsName + ":太贵了,不买"); }else{ System.out.println("[WomanVisitor]->" + ((Clothes)goods).goodsName + ":什么颜色都能接收,买了"); } }else if(goods instanceof Trousers){ if(((Trousers)goods).price > 500){ System.out.println("[WomanVisitor]->" + ((Trousers)goods).goodsName + ":太贵了,不买"); }else if(((Trousers)goods).getLength() > 8){ System.out.println("[WomanVisitor]->" + ((Trousers)goods).goodsName + ":太长了,不买"); }else{ System.out.println("[WomanVisitor]->" + ((Trousers)goods).goodsName + ":裤子越短约好,买了"); } } }}
测试类
public static void main(String[] args){ Shop shop = new Shop(); shop.add(new Clothes("限量版风衣",200, "black")); shop.add(new Clothes("披风",50, "red")); shop.add(new Clothes("衬衫",70, "blue")); shop.add(new Trousers("牛仔裤", 150, 18)); shop.add(new Trousers("喇叭裤", 80, 24)); shop.add(new Trousers("超短裤", 60, 5)); // 询问男人 shop.askAnswer(new ManVisitor()); // 询问女人 shop.askAnswer(new WomanVisitor());}
结果输出
[ManVisitor]->限量版风衣:太贵了,不买[ManVisitor]->披风:红色太丑了,不买[ManVisitor]->衬衫:价格颜色都能接收,买了[ManVisitor]->牛仔裤:太贵了,不买[ManVisitor]->喇叭裤:太长了,不买[ManVisitor]->超短裤:太短了,不买[WomanVisitor]->限量版风衣:什么颜色都能接收,买了[WomanVisitor]->披风:什么颜色都能接收,买了[WomanVisitor]->衬衫:什么颜色都能接收,买了[WomanVisitor]->牛仔裤:太长了,不买[WomanVisitor]->喇叭裤:太长了,不买[WomanVisitor]->超短裤:裤子越短约好,买了
优缺点
优点
- 将数据结构与算法解耦
- 增加操作很容易(增加访问者);
缺点
- 数据结构不易于扩展。
- 类变多了,也变复杂了,理解上不太直观。
码云
博客
欢迎关注我的个人微信订阅号:(据说这个头像程序猿专用)