委托学习——3. 委托的模板方法和回调函数(间接调用)

委托:把方法当作参数传递给其他方法


模板方法 ——“借用”指定的外部方法来产生结果
优点:实现了代码的重复使用,提高代码效率

特点:
1. 相当于填空题
2. 常位于代码中部
3. 委托有返回值

代码阅读顺序,最后阅读Main函数,先看下面的

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Security.Cryptography.X509Certificates;

namespace DelegateExample
{

    #region 模板方法——间接调用
    class Program
    {
        static void Main(string[] args)
        {
            //模板方法实现
            //首先创建工厂实例,才能调用他的两个实例方法去生产披萨或者玩具车
            ProductFactory productFactory = new ProductFactory();
            //然后需要打包工厂的实例
            WrapFactory wrapFactory = new WrapFactory();

            //因为模板方法接受委托类型的参数,所以需要准备委托类型的变量,把他当变量传进模板方法
            Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
            Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);

            //调用模板方法
            //wrapFactory.WrapProduct(func1);返回值是box类型,需要一个box类型接收
            Box box1 = wrapFactory.WrapProduct(func1);
            Box box2 = wrapFactory.WrapProduct(func2);

            Console.WriteLine(box1.Product.Name);
            Console.WriteLine(box2.Product.Name);

        }
    }

    class Product
    {
        public string Name { get; set; }//产品类
    }

    class Box
    {
        public Product Product { get; set; }//包装箱具有一个Product类型的属性,就是这个箱子里包装的产品
    }

    class WrapFactory//这个类负责把产品包装进盒子给用户
    {
        //模板方法
        public Box WrapProduct(Func<Product> getProduct)//接受一个委托类型的参数
        {
            //这个委托类型是Func,Func封装的方法可以返回一个Product类型的对象
            Box box = new Box();
            Product product = getProduct.Invoke();
            //getProduct委托的返回类型就是Product类型的,调用完肯定得到一个Product类型对象
            box.Product = product;//把box.Product这个属性的值设为刚才拿到的product
            return box;

        }
        //使用模板方法的好处是我的工厂类,box类都不需要再动了,只需要增加产品类即可
        //最大限度实现了代码的重复使用

    }

    //生产产品的工厂
    class ProductFactory
    {
        public Product MakePizza()//生产披萨
        {
            Product product = new Product();
            product.Name = "Pizza";
            return product;
        }

        public Product MakeToyCar()//生产小汽车
        {
            Product product = new Product();
            product.Name = "ToyCar";
            return product;
        }

    }


    #endregion
}

回调函数——调用指定的外部方法

特点:
1. 相当于“流水线”
2. 常位于代码末尾
3. 委托无返回值

以上面的代码为基础,增加回调函数如下:

 class Program
        {
            static void Main(string[] args)
            {
                //模板方法实现
                //首先创建工厂实例,才能调用他的两个实例方法去生产披萨或者玩具车
                ProductFactory productFactory = new ProductFactory();
                //然后需要打包工厂的实例
                WrapFactory wrapFactory = new WrapFactory();

                //因为模板方法接受委托类型的参数,所以需要准备委托类型的变量,把他当变量传进模板方法
                Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
                Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);

                //声明Log实例
                Logger logger = new Logger();
                Action<Product> log = new Action<Product>(logger.Log);

                //调用模板方法
                //wrapFactory.WrapProduct(func1);返回值是box类型,需要一个box类型接收
                Box box1 = wrapFactory.WrapProduct(func1,log);
                Box box2 = wrapFactory.WrapProduct(func2,log) ;
                //log方法在生产产品的时候就会执行,所以会比产品信息先打印在控制台,且只打印价格大于50的玩具车

                Console.WriteLine(box1.Product.Name);
                Console.WriteLine(box2.Product.Name);

            }
        }

            
        class Logger//记录程序状态,判断程序异常
        {
            public void Log(Product product)
            {
                Console.WriteLine("Product'{0}'creat at {1}.Price is {2}.",product.Name,DateTime.Now,product.Price);
                //将这个Log方法以回调函数的方式传递回模板方法里
            }
        }



        class Product
        {
            public string Name { get; set; }//产品
            public double Price { get;set; }//价格
        }

        class Box
        {
            public Product Product { get; set; }//包装箱具有一个Product类型的属性,就是这个箱子里包装的产品
        }

        class WrapFactory//这个类负责把产品包装进盒子给用户
        {
            //模板方法
            public Box WrapProduct(Func<Product> getProduct,Action<Product> logCallback)//对于没有返回值的方法应该使用Action委托
            {
                
                Box box = new Box();
                Product product = getProduct.Invoke();

                //添加逻辑决定是不是调用这个回调方法,假设产品价格大于50元时记录一下
                if (product.Price>=50)
                {
                    logCallback(product);
                }
                
                box.Product = product;//把box.Product这个属性的值设为刚才拿到的product
                return box;

            }
           

        }

        //生产产品的工厂
        class ProductFactory
        {
            public Product MakePizza()//生产披萨
            {
                Product product = new Product();
                product.Name = "Pizza";
                product.Price = 12;
                return product;
            }

            public Product MakeToyCar()//生产小汽车
            {
                Product product = new Product();
                product.Name = "ToyCar";
                product.Price = 100;
                return product;
            }

        }

结果如下:

 

        无论是模板方法还是回调函数,本质都是一样的,用委托类型的参数,封装一个外部的方法然后把这个方法传进方法的内部进行间接调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值