首页 > 其他分享 >访问者模式

访问者模式

时间:2022-11-11 23:55:30浏览次数:43  
标签:BaseJob Monitoring void 模式 override monitoring public 访问者

访问者模式有点小复杂,而且需要在实际的时候提前留好后门,下面通过简单的例子来介绍一下。场景就是邮件发送,通知客户怎么了怎么了,后面可能需要短信或者app也推。推之前或推送之后干点别的。

    public abstract class BaseJob { public abstract void Execute();public abstract void Accept(Monitoring monitoring);  }
    

这里的Execute方法就是正常操作,Accept就是预留的方法,通过它可以访问BaseJob 的实现,并且在不改动BaseJob 的情况下。那么Monitoring这个对象是什么呢?

    public abstract class Monitoring { public abstract void Monitor(SendEmail sendEmail); public abstract void Monitor(SendMessage sendMessage); public abstract void Monitor(SendOther endOther); }

所谓访问者Monitoring肯定是 BaseJob 的访问者,所以SendEmail 、SendMessage 、SendOther 都是BaseJob 的实现

 public class SendEmail : BaseJob
    {
        public override void Accept(Monitoring monitoring)
        {
            monitoring.Monitor(this);
        }

        public override void Execute()
        {
            Debug.WriteLine("邮件发送");
        }
    }

    public class SendMessage : BaseJob
    {
        public override void Accept(Monitoring monitoring)
        {
            monitoring.Monitor(this);
        }

        public override void Execute()
        {
            Debug.WriteLine("短信发送");
        }
    }
    public class SendOther : BaseJob
    {
        public override void Accept(Monitoring monitoring)
        {
            monitoring.Monitor(this);
        }

        public override void Execute()
        {
            Debug.WriteLine("App发送");
        }
    }
被访问的对象实现了,这个访问者也先给实现了吧。
  public class  AutoMonitor: Monitoring
    {
        public override void Monitor(SendEmail sendEmail)
        {
            Debug.WriteLine("邮件发送前");
            sendEmail.Execute();
            Debug.WriteLine("邮件发送后");
        }

        public override void Monitor(SendMessage sendMessage)
        {
            Debug.WriteLine("短信发送前");
            sendMessage.Execute();
            Debug.WriteLine("短信发送后");
        }

        public override void Monitor(SendOther endOther)
        {
            Debug.WriteLine("app发送前");
            endOther.Execute();
            Debug.WriteLine("app发送后");
        }
    }
下面就是怎么去调用的问题了。通过一个director类去包装一下访问者和被访问者。
    public class Director
    {
        private Monitoring _monitoring;
        public Director(Monitoring monitoring)
        {
            _monitoring = monitoring;
        }
        public void Start(BaseJob baseJob)
        {
            baseJob.Accept(_monitoring);
        }
    }
director的代码有点反转再反转的味道,Start方法是我们访问的入口,通过传一个被访问者对象,调用被访问者的Accept的方法,被访问者Accept又需要一个访问者的对象,这里就通过构造函数传进来的,目前为止都是抽象的,还未具体指定实现。
执行的流程就是start=>accept=》moitor,director入口,到basejob的accept拿到访问者monitor,mointor的实现moitor又可以拿到完整的被访问者basejob,这样就可以操纵被访问者了,而且可以在访问者前后添加任何扩展自己的操作。
有点绕,但是这个也实现了aop,跟装饰器效果也差不多了。
下面就是客户端的调用了,这里需要访问SendEmail 、SendMessage 、SendOther 都可以灵活的替换掉。
 public void TestV()
        {
            Monitoring monitoring = new AutoMonitor();
            Director director = new Director(monitoring);
            director.Start(new SendEmail());
        } 

 

写到这里差不多了,留个彩蛋自己体会:
public class Director
    {
        private Monitoring _monitoring;
        public Director(Monitoring monitoring)
        {
            _monitoring = monitoring;
        }
        public void Start(BaseJob baseJob)
        {
            baseJob.Accept(_monitoring);
        }
    }
    public class  AutoMonitor: Monitoring
    {
        public override void Monitor(BaseJob baseJob)
        {
            Debug.WriteLine("发送前动作");
            baseJob.Execute();
            Debug.WriteLine("发送后动作");
        }
    }

    public class SendEmail : BaseJob
    {
        public override void Accept(Monitoring monitoring)
        {
            monitoring.Monitor(this);
        }

        public override void Execute()
        {
            Debug.WriteLine("邮件发送");
        }
    }

    public class SendMessage : BaseJob
    {
        public override void Accept(Monitoring monitoring)
        {
            monitoring.Monitor(this);
        }

        public override void Execute()
        {
            Debug.WriteLine("短信发送");
        }
    }
    public class SendOther : BaseJob
    {
        public override void Accept(Monitoring monitoring)
        {
            monitoring.Monitor(this);
        }

        public override void Execute()
        {
            Debug.WriteLine("App发送");
        }
    }
    public abstract class BaseJob { public abstract void Execute();public abstract void Accept(Monitoring monitoring);  }
    
    public abstract class Monitoring { public abstract void Monitor(BaseJob baseJob);  }
   Monitoring monitoring = new AutoMonitor();
            Director director = new Director(monitoring);
            director.Start(new SendEmail());

            director.Start(new SendOther());   

 

 

 

 

标签:BaseJob,Monitoring,void,模式,override,monitoring,public,访问者
From: https://www.cnblogs.com/morec/p/16882472.html

相关文章

  • 给网站添加一个夜间模式
    最近发现了一个可以很简单给网站添加夜间模式的js库项目地址:https://darkmodejs.learn.uno/将下面的代码放到网站的头部或尾部,就会在网页的右下角出现一个按钮,点击即可......
  • Redis 集群模式的安装与配置【源码安装redis-7.0.5】
    Redis最新版下载地址:http://download.redis.io/releases/redis-7.0.5.tar.gz步骤如下:1)wget http://download.redis.io/releases/redis-7.0.5.tar.gz2)tar-zxf redis-7......
  • Java静态代理设计模式模式(多线程Runnable)
    静态代理设计模式,就是代理对象来帮你忙前忙后,你负责出席一下就好了。需要:1.实现相同的接口2.真实角色3.代理角色,里面有一个成员是接口对象(实际上是真实角色----接口实......
  • 设计模式学习(十三):观察者模式
    设计模式学习(十三):观察者模式作者:Grey原文地址:博客园:设计模式学习(十三):观察者模式CSDN:设计模式学习(十三):观察者模式观察者模式观察者模式是一种行为型模式。在对象之间......
  • 【JS】891- 高级 Promise 模式 - Promise缓存
    https://www.jonmellman.com/posts/promise-memoization 译者:ConardLi在本文中,我们将介绍常见的缓存实现在并发条件下存在的问题。然后我们将介绍如何修复它,并且在此过程......
  • 命令模式
    命令模式使用场景我反复强调,设个非常重要!因为纵使你有十八般武器,不知道什么时候用也是白搭。从定义上我们就可以看出其可以解决的问题。当需要将各种执行的动作抽象出来......
  • C#设计模式之建造者模式
      原文网址:https://www.jb51.net/article/254976.htm场景:我们的冒险家,现在需要去武器商店买一把兵器,有刀和剑两种武器,冒险者可以告诉武器商人需要哪一种武器,然后武器商......
  • 工厂模式
    工厂模式定义工厂类,及工厂方法,获取工厂里面的数据@Service@OrderpublicclassRuleFactory{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(R......
  • 软件设计模式白话文系列(六)代理模式
    1、描述代理模式属于结构型模式中的一种,通过对代理对象的调用来达到对原对象的增强、减弱作用。通过代理类的生成时机,我们将编译期就生成代理类的情况称之为静态代理模式,......
  • Scala模式匹配
    1 switch与default等效的是捕获所有的case_模式。如果没有模式匹配,抛出MatchError,每个case中,不用break语句。可以在match中使用任何类型,而不仅仅是数字。varresult=0;......