嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:
访问者模式是一种行为设计模式,它允许你在不改变类的结构的情况下增加新的操作。它是通过让对象决定哪些算法可以作用于它所包含的元素,从而增加新的操作类型来实现的。访问者模式是一种非常有用的模式,它可以将数据结构与数据操作分离,增加新的操作类型,而不改变数据结构。
在访问者模式中,有一个元素接口,它定义了所有元素类的公共方法,即接受访问的方法。然后,每个元素类都实现了这个接口,将自己的特定数据和操作封装起来。接着,有一个访问者接口,它定义了所有访问者的公共方法,即访问元素的方法。每个访问者类都实现了这个接口,并实现了访问元素的特定操作。
在客户端代码中,你可以创建元素对象和访问者对象,然后使用元素对象的 accept 方法接受访问者的访问。访问者会根据元素对象的类型调用相应的访问方法,从而实现了一种在不改变元素类的情况下增加新的操作的方式。
这些核心角色共同实现了访问者模式,可以在不改变类的结构的情况下增加新的操作,将数据结构与数据操作分离。
首先,我们定义一个“元素”接口:
- public interface Element {
- void accept(Visitor visitor);
- }
然后,我们创建一些具体的元素类。在这个例子中,我们只有两种元素:ConcreteElementA 和 ConcreteElementB:
- public class ConcreteElementA implements Element {
- @Override
- public void accept(Visitor visitor) {
- visitor.visit(this);
- }
- }
-
- public class ConcreteElementB implements Element {
- @Override
- public void accept(Visitor visitor) {
- visitor.visit(this);
- }
- }
接着,我们定义一个“访问者”接口:
- public interface Visitor {
- void visit(ConcreteElementA elementA);
- void visit(ConcreteElementB elementB);
- }
然后我们创建一些具体的访问者类:在这个例子中,我们只有一种访问者:ConcreteVisitor:
- public class ConcreteVisitor implements Visitor {
- @Override
- public void visit(ConcreteElementA elementA) {
- System.out.println("ConcreteVisitor visited ConcreteElementA");
- }
-
- @Override
- public void visit(ConcreteElementB elementB) {
- System.out.println("ConcreteVisitor visited ConcreteElementB");
- }
- }
最后,我们在客户端代码中使用访问者模式:
- public class Client {
- public static void main(String[] args) {
- Element elementA = new ConcreteElementA();
- Element elementB = new ConcreteElementB();
- Visitor visitor = new ConcreteVisitor();
- elementA.accept(visitor); // 输出 "ConcreteVisitor visited ConcreteElementA"
- elementB.accept(visitor); // 输出 "ConcreteVisitor visited ConcreteElementB"
- }
- }
要说三国中最创业最牛的还属在桃园拜把子的刘关张,谁能想一个编草鞋的、一个杀猪的、还有一个在逃犯,居然这么厉害,从零成功打下江山还立国了,当然最后最守住江山确实很可惜;但要说这成功的秘密,还得刘备这当大哥的会画饼,并且关、张这种狠人,还只吃他的饼,你说厉害不。在创业的路上,刘备带着两个迷弟是从一个失败走向另一个失败,但是刘、关、张之间的结构关系是相当的稳定,“我听大哥的!”,“俺也一样!”。
如果把刘关张套用到访问者模式中,刘备实际上相当于具体的访问者,最稳定的技能就是哭和画饼;关、张就是具体元素,结构非常稳定,就是只听大哥的,如果想指挥他们,就得通过大哥发话才好使。
下面通过伪代码示例说明一个访问者模式如何实现。
- /**
- * 抽象大哥
- */
- public interface DaGe {
- /**
- * 给关羽画饼
- * @param zhangFei
- */
- void huabing(GuanYu zhangFei);
-
- /**
- * 给张飞画饼
- * @param zhangFei
- */
- void huabing(ZhangFei zhangFei);
- }
- /**
- * 抽象猛将
- */
- public interface MengJiang {
- /**
- * 接受命令
- * @param daGe
- */
- void accept(DaGe daGe);
- }
- public class GuanYu implements MengJiang {
- private String name = "云长";
-
- public String getName() {
- return name;
- }
-
- @Override
- public void accept(DaGe daGe) {
- daGe.huabing(this);
- System.out.println(this.name + ":我听大哥的!");
-
- }
- }
- public class ZhangFei implements MengJiang {
- private String name = "翼德";
-
- public String getName() {
- return name;
- }
-
- @Override
- public void accept(DaGe daGe) {
- daGe.huabing(this);
- System.out.println(this.name + ":俺也一样!");
- }
- }
- public class LiuBei implements DaGe{
- public String name="刘备";
-
- @Override
- public void huabing(GuanYu zhangFei) {
- String msg=this.name+":二弟,努把力,斩落敌将,晚上给你加个鸡腿!";
- System.out.println(msg);
- }
-
- @Override
- public void huabing(ZhangFei zhangFei) {
- String msg=this.name+":三弟,把家产卖了资助我打江山吧,到时候给你娶个嫂嫂!";
- System.out.println(msg);
- }
- }
- public class Client {
- public static void main(String[] args) {
- DaGe daGe = new LiuBei();
- MengJiang guanyu = new GuanYu();
- MengJiang zhangfei = new ZhangFei();
- guanyu.accept(daGe);
- zhangfei.accept(daGe);
- }
- }
后来孔明做了刘备的军师,代替刘备行使大哥发号使令的权利后,一点点开始成功起来。那么增加孔明这个代理大哥了,铁三角的结构依然是不变的,怎么用代码实现呢?
1、实现大哥的接口,代替刘备向关张发号使令
- public class KongMing implements DaGe {
- private String name = "孔明";
-
- @Override
- public void huabing(GuanYu zhangFei) {
- String msg = this.name + ":" + zhangFei.getName() + ",悄悄埋伏,守好此道,必能擒住曹贼!";
- System.out.println(msg);
- }
-
- @Override
- public void huabing(ZhangFei zhangFei) {
- String msg = this.name + ":" + zhangFei.getName() + ",且勿酗酒鞭打士兵,好好打仗,我给你娶个弟妹!";
- System.out.println(msg);
- }
- }
2、修改客户端业务
- public class Client {
- public static void main(String[] args) {
- DaGe daGe = new LiuBei();
- MengJiang guanyu = new GuanYu();
- MengJiang zhangfei = new ZhangFei();
- guanyu.accept(daGe);
- zhangfei.accept(daGe);
- System.out.println("--------------");
- daGe = new KongMing();
- guanyu.accept(daGe);
- zhangfei.accept(daGe);
- }
- }
了解了什么是访问者模式、有哪些核心角色以及如何实现后,这里再梳理一下访问者模式适用于哪些业务场景:
需要特别注意的是,访问者模式通过将数据结构和操作分离开来,使得数据结构可以保持稳定,而操作可以随意扩展。这种解耦有助于提高系统的灵活性和可复用性。然而,访问者模式也有一些缺点,例如增加新的数据结构困难、违反了依赖倒置原则等,使用时需要根据具体情况权衡利弊。
综上所述,访问者模式具有优秀的扩展性和灵活性,但也存在一些缺点需要注意。使用时需要根据具体情况权衡利弊。