• 访问者模式


    访问者模式有点小复杂,而且需要在实际的时候提前留好后门,下面通过简单的例子来介绍一下。场景就是邮件发送,通知客户怎么了怎么了,后面可能需要短信或者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());   

     

     补上计算器的例子:
    复制代码
     public class CalClient
        {
            protected IColleague _colleague;
            public CalClient(IColleague colleague)
            {
                _colleague = colleague;
            }
            public decimal Start(ICalculator calculator)
            {
               return calculator.Accept(_colleague);
            }
        }
        public class ColleaguaA : IColleague
        {
            protected List<decimal> _items;
            public ColleaguaA(List<decimal> items)
            {
                _items = items;
            }
            public decimal Invoke(ICalculator calculator)
            {
               return calculator.Calculate(_items.ToArray());
            }
        }
        public class ColleaguaB : IColleague
        {
            private List<decimal> items;
    
            public List<decimal> Items { get => items; set => items = value; }
    
            public decimal Invoke(ICalculator calculator)
            {
                Trace.WriteLine("items赋值判断");
                var result = calculator.Calculate(Items.ToArray());
                Trace.WriteLine(" save to db");
                return result;
            }
        }
    
        public interface ICalculator {  decimal Calculate(params decimal[] items); decimal Accept(IColleague colleague); }
        public interface IColleague { decimal Invoke(ICalculator calculator); }
    
    
        public class AddCalculator : ICalculator
        {
            public decimal Accept(IColleague colleague)
            {
                return colleague.Invoke(this);
            }
    
            public decimal Calculate(params decimal[] items)
            {
                return items.Aggregate((a, b) => a + b);
            }
        }
        public class SubCalculator : ICalculator
        {
            public decimal Accept(IColleague colleague)
            {
                return colleague.Invoke(this);
            }
    
            public decimal Calculate(params decimal[] items)
            {
                return items.Aggregate((a, b) => a - b);
            }
        }
        public class MulCalculator : ICalculator
        {
            public decimal Accept(IColleague colleague)
            {
                return colleague.Invoke(this);
            }
    
            public decimal Calculate(params decimal[] items)
            {
                return items.Aggregate((a, b) => a * b);
            }
        }
        public class DivCalculator : ICalculator
        {
            public decimal Accept(IColleague colleague)
            {
                return colleague.Invoke(this);
            }
    
            public decimal Calculate(params decimal[] items)
            {
                return items.Aggregate((a, b) => a / b);
            }
        }
    复制代码

     

    复制代码
       ColleaguaA colleaguaA = new ColleaguaA(new List<decimal> { 12, 34, 56 });
                ColleaguaB colleaguaB = new ColleaguaB();
                colleaguaB.Items = new List<decimal> { 1, 2, 3, 4, 5 };
                CalClient calClient = new CalClient(colleaguaA);
                calClient.Start(new AddCalculator());
                CalClient otherClient = new CalClient(colleaguaB);
                otherClient.Start(new MulCalculator());
    复制代码

     

     

     

  • 相关阅读:
    JVM 内存管理 你知道多少
    目标检测算法——YOLOV6
    解题-->在线OJ(十九)
    前端开发常用技术工具网址导航汇总
    【洛谷P1622】释放囚犯【区间DP】
    Redis高可用原理 主从哨兵集群
    ROS环境下使用WHEELTEC N100惯导模块
    【精讲】async,await简介及与Ajax合用案例(内含面试内容)
    常用User-Agent
    JAVAEE初阶相关内容第十弹--多线程(初阶)
  • 原文地址:https://www.cnblogs.com/morec/p/16882472.html