在日常使用中,我们一般是将委托,当作方法的参数,传到参数里面去.
比如你写了一个方法,这个方法有一个委托类型的参数
1,首先,委托它封装了一个方法
2,我们在这个方法体里使用传进来的这个委托,间接的去调用委托封装了的方法
这样就形成了动态调用方法的一个结构
像这种把委托当作参数调用的方法,又

具体分为两种

1.模板方法

这个方法相当于有一个填空题,这个空白的地方由传进来的委托方法帮你进行填空,然后你继续写接下来的代码.
为什么叫模板方法呢,因为你写了这样一个模板,这个模板有一处是不确定的,这个不确定的部分,就靠你传进来的委托参数所包含的方法来进行填补.
实例:

using System;

namespace DeleGate_CallBack
{
    class Program
    {
        static void Main(string[] args)
        {
            ProductFactory productFactory = new ProductFactory();//生成包装工厂类的实例,然后我们才能调用它的方法
            WrapFactory wrapFactory = new WrapFactory();//包装工厂的实例
            //因为上面的模板方法接收委托类型参数,所以我们先定义一个委托类型的参数
            Func<Product> func1 = new Func<Product>(productFactory.MakePizz); // 我们先把披萨方法传递给委托方法func1 记住返回类型和参数类型必须兼容
            Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);//然后我们再如法炮制一个委托方法,把生产小汽车的方法递给委托方法func2

            Box box1 = wrapFactory.WrapProduct(func1); //包装工厂是一个Box类,需要一个Box类的参数接收它的返回值;
            Box box2 = wrapFactory.WrapProduct(func2);
            Console.WriteLine(box1.product.Name);//它会输出Pizza
            Console.WriteLine(box2.product.Name);//它会输出ToyCar
        }
    }
    class Product  //Product类,任何产品都有自己的名字
    {
        public string Name { get; set; } //还记得吗?prop不是propfull的话,IDE会帮你进行简易声明,但是不具有安全性.可以直接用赋值符号'=',赋值给Name
    }
    class Box
    {
        public Product product { get; set; } //每个包装箱具有一个属性,是Product类型的 就是这个箱子里所包装的产品.
    }

    class WrapFactory  //包装工厂--专门负责把产品装进盒子
    {
        public Box WrapProduct(Func<Product> getProduct)//模板方法,接收一个委托类型的参数,它返回一个Product类型的对象
        {
            Box box = new Box();//首先我在自己的类里面创建一个自己的实例(箱子)
            Product product = getProduct.Invoke(); //由于委托函数它拿到的返回值是一个Product类型,所以赋值给product
            box.product = product;
            return box;
        }

    }
    class ProductFactory  //生产产品的工厂
    {
        public Product MakePizz() //生产披萨
        {
            Product product = new Product();
            product.Name = "Pizza";
            return product;
        }
        public Product MakeToyCar() //生产玩具小汽车
        {
            Product product = new Product();
            product.Name = "ToyCar";
            return product;
        }
    }

}

使用模板方法,好处就是product,box等等一切的类,不用再改动了,如果我们新增了生产其他物品,只需要扩展ProductFactoy生产工厂这个类就行了.只要你把生产的工厂新增一个生产方法,传递给委托函数,然后调用这个委托函数,程序就会把你新的生产方法生产出来的东西拿去打包,这样完美的实现了代码的复用
学完了委托的模板方法,100分就拿走了200分拉,接下来的回调方法,占比800分

2.回调方法

回调方法,就Tm就有点难度了,标题的难度1000,基本900是在这里,要懂得使用回调方法,首先要知道什么叫回调,它的英文单词是CallBack.
它指的是这样的一种场景
有一天,我碰到你了,那我就递上我的名片,告诉你,如果需要我,就打这个电话.找我就是调用我的某个功能,来帮你解决一些问题.
如果你不需要我帮忙呢,那么你就永远不会去打这个电话.
现在,我和你之间,就构成了这种回调关系.
所谓回调方法呢,就是我可以调用它,也可以不调用它,用的着的时候,我就调用它.
回调方法还给了我们一个机会,让我们动态的选择后续将被调用的方法
这就相当于,不止我一个人给了你名片,而是很多人都给了你名片
当你需要帮助的时候,你可以在这一大把名片里找出一个电话来,然后打他的电话,向他寻求帮助.
当以回调方法来使用委托的时候,我们要做的是把委托类型的参数,传进主调方法里面去
被传进主调方法里面的委托类型的参数呢,它内部会封装了一个被回调的方法,就是我们常说的那个回调方法.
主调函数会根据自己的逻辑来决定,我是不是调用这个回调方法.一般情况下,我的主调方法会在主要逻辑执行完了之后,决定是不是调用这个回调方法.
回调方法一般都会位于主调方法代码的末尾之处.
而且呢,回调方法一般的用处是来执行一些后续的工作,它构成一个流水线的结构,所以说回调方法,一般是没有返回值的.
回调方法,也叫好莱坞方法
意思就是,一个演员,去好莱坞面试,面试官说:你回去等电话,你不要打电话,你等电话,如果我们选中你的话呢,我们会打给你
实例

using System;

namespace DeleGate_CallBack
{
    class Program
    {
        static void Main(string[] args)
        {
            ProductFactory productFactory = new ProductFactory();//生成包装工厂类的实例
            WrapFactory wrapFactory = new WrapFactory();//包装工厂的实例

            Func<Product> func1 = new Func<Product>(productFactory.MakePizz); 
            Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
            Logger logger = new Logger();//1.创建Logger的实例
            Action<Product> log = new Action<Product>(logger.log);//创建无返回值的委托
            Box box1 = wrapFactory.WrapProduct(func1, log);//调用的时候新增一个参数
            Box box2 = wrapFactory.WrapProduct(func2, log);
            Console.WriteLine(box1.product.Name);
            Console.WriteLine(box2.product.Name);
        }
    }
    class Logger
    {
        public void log(Product product)
        {
            Console.WriteLine("产品{0}被创建 创建时间{1},产品定价{2}",product.Name,DateTime.UtcNow,product.Price);//utcNow不带时区.且方法被调用立即打印输出
        }
    }
    class Product  //Product类,任何产品都有自己的名字
    {
        public string Name { get; set; }
        public double Price { get; set; }
    }
    class Box
    {
        public Product product { get; set; } 
    }

    class WrapFactory  //包装工厂
    {
        public Box WrapProduct(Func<Product> getProduct,Action<Product> LogCallBack)//Action不具有返回值,对应Logger方法,它接收一个Product类型的参数
        {
            Box box = new Box();
            Product product = getProduct.Invoke();
            if (product.Price>50)  //现在我们来添加逻辑,如果产品的价格大于50元,我们才Logger,也就是条件成立才CallBack
            {
                LogCallBack(product);
            }
            box.product = product;
            return box;
        }

    }
    class ProductFactory  //生产产品的工厂
    {
        public Product MakePizz() 
        {
            Product product = new Product();
            product.Name = "Pizza";
            product.Price = 33; //新增价格信息
            return product;
        }
        public Product MakeToyCar() 
        {
            Product product = new Product();
            product.Name = "ToyCar";
            product.Price = 100;//新增价格信息
            return product;
        }
    }

}

如果你对第一个模板方法已经了解了的话呢,那么你对第二个回调方法其实也很容易理解,这样子,你也仅仅之拿到了300分.真正的700分,在下一篇
和我一样的初学者呢,其实只是在逻辑上非常容易绕晕,因为他们调来调去的
我调用你,你调用它,它委托它,它执行它.所以其实不用太在意,当你以后需要用的时候,回来看看,用几次,就完全熟悉了,在不熟悉的情况下呢,你只需要对逻辑能够理解即可,而且至少需要间隔一天去理解一次,总共两次,就可以继续向下学习.

最后修改:2022 年 12 月 05 日
如果觉得我的文章对你有用,请随意赞赏