文档章节

设计模式 之 访问者模式

GMarshal
 GMarshal
发布于 11/16 08:55
字数 1133
阅读 12
收藏 0

设计模式 之 访问者模式

概念

核心理念:将数据结构与算法分离。

使用场景:数据结构不变动,算法经常变动。

  • 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 List<Goods> goodsList = 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]->超短裤:裤子越短约好,买了

优缺点

优点

  • 将数据结构与算法解耦
  • 增加操作很容易(增加访问者);

缺点

  • 数据结构不易于扩展。
  • 类变多了,也变复杂了,理解上不太直观。

码云

https://gitee.com/gmarshal/foruo-learn-java/tree/master/src/main/java/com/foruo/learn/designmode/visitor

博客

https://my.oschina.net/gmarshal/blog/2876986

欢迎关注我的个人微信订阅号:(据说这个头像程序猿专用)

输入图片说明

© 著作权归作者所有

共有 人打赏支持
GMarshal
粉丝 19
博文 58
码字总数 46067
作品 0
南京
程序员
私信 提问
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
0
0
《PHP设计模式大全》系列分享专栏

《PHP设计模式大全》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第1/3页 php设计模式介绍之值对象模式第1/5页...

kaixin_code
11/06
0
0
设计模式Java Design Pattern-工厂方法模式FactoryMethod

我的博客 一、 设计模式的分类 大体可以分为三类: 创建型模式(5个) 单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式 结构性模式(7个) 适配器模式、装饰器模式、代理模式、...

勇敢写信
03/22
0
0
设计模式22——Visitor设计模式

Visitor访问者设计模式是在不修改已有程序结构的前提下,通过添加额外的“访问者”来完成对已有代码功能的提升。 Visitor访问者设计模式的角色: (1) 访问者角色(Visitor):声明一个访问接...

小米米儿小
2014/01/27
0
0
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
06/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

使用CURL检测Clinet侧发起的HTTP请求各阶段时间

第一、HTTP请求的过程介绍 一个HTTP请求,涉及多个阶段 1、DNS解析域名 2、请求从Clinet路由至Server,Clinet与Server建立TCP连接 3、如果使用了HTTPS,还涉及SSL连接的建立 4、server开始准...

李玉长
17分钟前
0
0
Flume+Kafka双剑合璧玩转大数据平台日志采集

概述 大数据平台每天会产生大量的日志,处理这些日志需要特定的日志系统。 一般而言,这些系统需要具有以下特征: 构建应用系统和分析系统的桥梁,并将它们之间的关联解耦; 支持近实时的在线...

java菜分享
23分钟前
1
0
Jenkins 分布式-管理节点

什么是Jenkins的分布式构建: Jenkins的分布式构建,在Jenkins的配置中叫做节点;能够让同一套代码或项目在不同的环境分发 节点配置 系统设置 - 节点管理 - 新建节点 插件 Node and Label par...

以谁为师
29分钟前
0
0
图片无限轮播

<!doctype html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, max......

shawnDream
32分钟前
2
0
js 在==时,则会有一些让人难以理解的陷阱

在==时,则会有一些让人难以理解的陷阱。 (function () { var undefined; undefined == null; // true 1 == true; //true 2 == true; // false 0 == false; // true 0 == ''; // true NaN ==......

之渊
34分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部