建立网站的步骤及费用,有经验的手机网站建设,泰安房产中介公司,传奇网页版在线玩一、定义#xff1a;访问者模式 访问者模式#xff1a;核心在于同一个事物不同视角下的访问信息不同。 在一个稳定的数据结构下#xff0c;例如用户信息、雇员信息等#xff0c;增加易变的业务访问逻辑。为了增强扩展性#xff0c;将两部分的业务解耦的一种设计模式。
二…一、定义访问者模式 访问者模式核心在于同一个事物不同视角下的访问信息不同。 在一个稳定的数据结构下例如用户信息、雇员信息等增加易变的业务访问逻辑。为了增强扩展性将两部分的业务解耦的一种设计模式。
二、模拟场景模板模式 模拟校园中的学生和老师对于不同用户的访问视角。在这个案例场景我们模拟校园中由学生和老师两种身份的用户那么对于家长和校长关心的角度来看他们的视角是不同的。 家长更关心孩子的成绩和老师的能力校长更关心老师所在班级学生的人数和升学率。 那么这样 学生 和 老师 就是一个固定信息的内容而想让不同视角的用户获取关心的信息就比较适合使用访问者模式来实现从而让实体与业务解耦增强扩展性。 但访问者模式的整体类结构相对复杂需要梳理清除再开发。
三、改善代码模访者模式 访问者模式的类结构相对其他设计模式来说比较复杂但这样的设计模式能阔开你对代码结构的新认知用这样的思维不断的建设处更好的代码架构。 这个案例的核心逻辑 建立用户抽象类和抽象访问方法再由不同的用户实现老师和学生。建立访问者接口用于不同人员的访问操作家长和校长。最终是对数据的看板建设用于实现不同视角的访问结果输出。
3.0 引入依赖
dependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --dependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.62/version/dependency!-- LOGGING begin --dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-api/artifactIdversion1.7.5/version/dependencydependencygroupIdorg.slf4j/groupIdartifactIdjcl-over-slf4j/artifactIdversion1.7.5/version/dependencydependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.0.9/versionexclusionsexclusionartifactIdslf4j-api/artifactIdgroupIdorg.slf4j/groupId/exclusion/exclusions/dependency
/dependencies3.1 工程结构
design-step-22
|——src|——main|--java|--com.lino.design|--user| |--impl| | |--Student.java| | |--Teacher.java| |--User.java|--visitor| |--impl| | |--Parent.java| | |--Principal.java| |--Visitor.java|-DataView.java|--test|--com.lino.design.test|-ApiTest.java3.2 访问者模式结构图 上面的视图展示了代码的核心结构主要包括不同视角下的不同用户访问模型。访问者模式的核心组成部分visitor.visit(this) 这个方法在每一个用户实现类里包括Student、Teacher。
3.3 用户抽象类和实现
3.3.1 定义用户抽象类 User.java package com.lino.design.user;import com.lino.design.visitor.Visitor;/*** description: 用户类*/
public abstract class User {/*** 姓名*/public String name;/*** 身份重点班、普通班 | 特级教师、普通教师、实习教师*/public String identity;/*** 班级*/public String clazz;public User(String name, String identity, String clazz) {this.name name;this.identity identity;this.clazz clazz;}/*** 核心访问方法** param visitor 访问者*/public abstract void accept(Visitor visitor);
}基本信息包括姓名、身份、班级也可以是一个业务用户属性类。定义核心抽象方法abstract void accept(Visitor visitor) 这个方法是为了让后续的用户具体实现者都能提供出一个访问方法供外部使用。
3.3.2 实现用户信息-学生类 Student.java package com.lino.design.user.impl;import com.lino.design.user.User;
import com.lino.design.visitor.Visitor;
import java.util.Random;/*** description: 学生类*/
public class Student extends User {public Student(String name, String identity, String clazz) {super(name, identity, clazz);}Overridepublic void accept(Visitor visitor) {visitor.visit(this);}/*** 排名*/public int ranking() {return (int) (Math.random() * 100);}/*** 数量*/public int count() {return 105 - new Random().nextInt(10);}
}3.3.3 实现用户信息-老师类 Teacher.java package com.lino.design.user.impl;import com.lino.design.user.User;
import com.lino.design.visitor.Visitor;
import java.math.BigDecimal;
import java.util.Random;/*** description: 老师类*/
public class Teacher extends User {public Teacher(String name, String identity, String clazz) {super(name, identity, clazz);}Overridepublic void accept(Visitor visitor) {visitor.visit(this);}/*** 升本率*/public double entranceRatio() {return BigDecimal.valueOf(Math.random() * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();}
}这里实现了老师类和学生类都提供了父类的构造函数。 在 accept 方法中提供了本地对象的访问。visitor.visit(this); 老师和学生类又都单独提供了各自的特性方法升学率(entranceRatio)、排名(ranking)类似这样的方法可以按照业务需求进行扩展。
3.4 访问者接口及其实现
3.4.1 定义访问数据接口 Visitor.java package com.lino.design.visitor;import com.lino.design.user.impl.Student;
import com.lino.design.user.impl.Teacher;/*** description: 访问者接口*/
public interface Visitor {/*** 访问学生信息** param student 学生类*/void visit(Student student);/*** 访问老师信息** param teacher 老师类*/void visit(Teacher teacher);
}访问接口比较简单相同的方法名称不同的入参用户类型。让具体的访问者类在实现时可以关注每一种用户类型的具体访问数据对象例如升学率和排名。
3.4.2 访问者实现类-家长类 Parent.java package com.lino.design.visitor.impl;import com.lino.design.user.impl.Student;
import com.lino.design.user.impl.Teacher;
import com.lino.design.visitor.Visitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** description: 家长类*/
public class Parent implements Visitor {private Logger logger LoggerFactory.getLogger(Parent.class);Overridepublic void visit(Student student) {logger.info(学生信息 姓名{} 班级{} 排名{}, student.name, student.clazz, student.ranking());}Overridepublic void visit(Teacher teacher) {logger.info(老师信息 姓名{} 班级{} 级别{}, teacher.name, teacher.clazz, teacher.identity);}
}家长关注自己家孩子的排名老师的班级和教学水平。
3.4.3 访问者实现类-校长类 Principal.java package com.lino.design.visitor.impl;import com.lino.design.user.impl.Student;
import com.lino.design.user.impl.Teacher;
import com.lino.design.visitor.Visitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** description: 校长类*/
public class Principal implements Visitor {private Logger logger LoggerFactory.getLogger(Principal.class);Overridepublic void visit(Student student) {logger.info(学生信息 班级{} 人数{}, student.clazz, student.count());}Overridepublic void visit(Teacher teacher) {logger.info(老师信息 姓名{} 班级{} 升学率{}, teacher.name, teacher.clazz, teacher.entranceRatio());}
}校长关注学生的名称和班级老师对这个班级的升学率。
3.5 数据看板 DataView.java package com.lino.design;import com.lino.design.user.User;
import com.lino.design.user.impl.Student;
import com.lino.design.user.impl.Teacher;
import com.lino.design.visitor.Visitor;
import java.util.ArrayList;
import java.util.List;/*** description: 数据看板*/
public class DataView {ListUser userList new ArrayList();public DataView() {userList.add(new Student(谢飞机, 重点班, 一年一班));userList.add(new Student(windy, 重点班, 一年一班));userList.add(new Student(大毛, 普通班, 二年三班));userList.add(new Student(Shing, 普通班, 三年四班));userList.add(new Teacher(BK, 特级教师, 一年一班));userList.add(new Teacher(娜娜Goddess, 特级教师, 一年一班));userList.add(new Teacher(dangdang, 普通教师, 二年三班));userList.add(new Teacher(泽东, 实习教师, 三年四班));}public void show(Visitor visitor) {for (User user : userList) {user.accept(visitor);}}
}首先在这个类中初始化了基本的数据学生和老师的信息。并提供了一个展示类通过传入不同的 访问者(家长、校长) 而差异化的打印信息。
3.6 单元测试 ApiTest.java package com.lino.design.test;import com.lino.design.DataView;
import com.lino.design.visitor.impl.Parent;
import com.lino.design.visitor.impl.Principal;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** description: 单元测试*/
public class ApiTest {private Logger logger LoggerFactory.getLogger(ApiTest.class);Testpublic void test_show() {DataView dataView new DataView();logger.info(\r\n家长视角访问);dataView.show(new Parent());logger.info(\r\n校长视角访问);dataView.show(new Principal());}
}测试类提供了三个商品连接也可以是其他商品的连接。爬取的成功模拟爬取京东商品可以替换为其他商品服务。new JDNetMall、 new DangDangNetMall 、 new TaoBaoNetMall 测试结果 14:14:27.268 [main] INFO com.lino.design.test.ApiTest -
家长视角访问
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 学生信息 姓名谢飞机 班级一年一班 排名47
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 学生信息 姓名windy 班级一年一班 排名26
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 学生信息 姓名大毛 班级二年三班 排名46
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 学生信息 姓名Shing 班级三年四班 排名2
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 老师信息 姓名BK 班级一年一班 级别特级教师
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 老师信息 姓名娜娜Goddess 班级一年一班 级别特级教师
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 老师信息 姓名dangdang 班级二年三班 级别普通教师
14:14:27.273 [main] INFO com.lino.design.visitor.impl.Parent - 老师信息 姓名泽东 班级三年四班 级别实习教师
14:14:27.273 [main] INFO com.lino.design.test.ApiTest -
校长视角访问
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 学生信息 班级一年一班 人数102
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 学生信息 班级一年一班 人数103
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 学生信息 班级二年三班 人数98
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 学生信息 班级三年四班 人数99
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 老师信息 姓名BK 班级一年一班 升学率45.81
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 老师信息 姓名娜娜Goddess 班级一年一班 升学率27.52
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 老师信息 姓名dangdang 班级二年三班 升学率51.94
14:14:27.273 [main] INFO c.lino.design.visitor.impl.Principal - 老师信息 姓名泽东 班级三年四班 升学率37.5通过测试结果可以看到家长和校长的访问视角同步数据也是差异化的。家长视角看到学生的排名排名47、排名26、排名46、排名2 。校长视角看到班级升学率升学率45.81、升学率27.52、升学率51.94、升学率37.5 。通过这样的测试结果可以看到访问者模式的初心和结果在适合的场景运用合适的模式非常有利于程序开发。
四、总结访问者模式
通过上面的业务场景可以看到在嵌入访问者模式后可以让整个工程结构变得容易添加和修改。 也就做到了系统之间的解耦不至于为了不同类型信息的访问而增加很多多余的 if 判断或者类的强制转换。也就是通过这样的设计模式而让代码结构更加清晰。 另外在实现的过程可能发现定义抽象类的时候还需要等待访问者接口的定义。 这样的设计首先从实现上会让代码的组织变得有些难度。另外从设计模式原则的角度来看违背了迪米特原则也就是最少知道原则。因此在使用上一定要符合场景的运用以及提取这部分设计思想的精髓。