zoukankan      html  css  js  c++  java
  • 委托的一般使用

    模板方法:

    有这么一家厂家,做披萨和玩具车两种Product,并且给他们的产品装在不同的包装盒Box里,我们通过委托的方式给他们的产品装上包装盒。

    产品类

        class Product
        {
            public string Name { get; set; }
        }
    

    包装盒类

        class Box
        {
            public Product Product { get; set; }
        }
    

    包装车间类

    这里多说一句,包装车间类里有包装产品方法WarpProduct(),这个方法的参数是委托类型的变量getPorduct,
    意味着我们要先实例化委托(用委托变量“引用”这个实例)再传入这个委托类型的变量

        class WarpFactory
        {
            public Box WarpProduct(Func<Product> getPorduct)
            {
                Box box = new Box();
                Product product = getPorduct.Invoke();//Product类的product变量去接Product类型对象。
                box.Product = product;
                return box;
            }
        }
    

    这个委托的返回类型是product,则返回类型是product类型的对象

    产品工厂类

        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;
            }
        }
    

    主函数类

        class Program
        {
            static void Main(string[] args)
            {
                ProductFactory productfactory = new ProductFactory();
                Func<Product> funcpizza = new Func<Product>(productfactory.MakePizza);
                Func<Product> functoycar = new Func<Product>(productfactory.MakeToyCar);
                WarpFactory warpfactory = new WarpFactory();
                Box pizzabox = warpfactory.WarpProduct(funcpizza);
                Box toycarbox = warpfactory.WarpProduct(functoycar);
                Console.WriteLine(pizzabox.Product.Name);
                Console.WriteLine(toycarbox.Product.Name);
            }
        }
    

    以做Pizza为例:

    先创建funcpizza 委托,封装了MakePizza这个方法,
    WarpProduct类的WarpProduct方法中

    Product product = getPorduct.Invoke();
    

    调用了funcpizza委托,
    就跳转到ProductFactory类中MakePizza这个方法里(间接调用)
    MakePizza方法创建了一个Product类型的pizza对象
    调用完成后会返回间接调用的起点处

    Product product = getPorduct.Invoke();
    

    并且通过委托拿到一个Product类型的对象(pizza),并且

    box.Product = product;
    

    这个对象(pizza)就传入了box对象,在主函数中这个box又被赋值给对应的Box类型对象(如Box类的pizzabox实例)
    就完成了对产品的包装。
    结果:

    这就是我们的模板方法,

    逻辑在上面已经说明。
    可以修改的逻辑是委托的调用getPorduct.Invoke(),传进来的委托封装的什么方法,在这里可以得到这个方法产出的产品。
    这样写的好处是,我们只需要扩展产品类,而不需要动其他任何地方,最大限度的实现了代码的重复使用。

    回调方法(Callback):

    回调方法是通过委托类型的参数传进主调用方法的一个被调入方法,
    主调用方法可以根据自己的逻辑来决定调用还是不调用这个方法。
    又叫好莱坞方法:主办方让面试的求职者回去等电话。
    总结一下就是:方法作为参数,一定条件触发后,调用这个方法

    举例说明:
    我们先对我们之前的产品类进行改造,加入price属性。

    产品类

       class Product
        {
            public string Name { get; set; }
            public double Price { get; set; }
        }
    

    然后新增一个Logger类,来记录运行状态,Log方法来记录状态没有返回值,这里记录的是创建时间

    Logger类

        class Logger
        {
            public void Log(Product product)
            {
                Console.WriteLine("Product'{0}',created at {1}.",product.Name, DateTime.UtcNow, product.Price);//DataTime.Now有时区
            }
        }
    

    我们把Log方法,以回调方法的形式传入我们的模板方法里,
    对于没有返回值的方法(Log),我们用Action委托。
    Action委托可以接收类型参数。
    当产品价格>50的时候我们就调用Log方法。

    包装车间类

        class WarpFactory
        {
            public Box WarpProduct(Func<Product> getPorduct, Action<Product> logCallback)
            {
                Box box = new Box();
                Product product = getPorduct.Invoke();//Product类的product变量去接Product类型对象。
                box.Product = product;//传给box.product
                if (product.Price > 50)
                {
                    logCallback.Invoke(product);
                }
                return box;
            }
        }
    

    Action 这个委托没有返回值,
    要求委托的方法必须是无返回值void,参数类型必须是Product
    因此写成logCallback.Invoke(product);Logger类的Log()的确没有返回值,实例product的类型的是Product。

    修改一下产品工厂类,给每个产品赋价值

    产品工厂类

        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;
            }
        }
    

    回到主方法里,实例化Logger类的实例为logger取得其方法并以之创建委托log,并且传入模板方法。

    主函数

        class Program
        {
            static void Main(string[] args)
            {
                ProductFactory productfactory = new ProductFactory();
                Logger logger = new Logger();
                Action<Product> funclog = new Action<Product>(logger.Log);
                Func<Product> funcpizza = new Func<Product>(productfactory.MakePizza);
                Func<Product> functoycar = new Func<Product>(productfactory.MakeToyCar);
                WarpFactory warpfactory = new WarpFactory();
                Box pizzabox = warpfactory.WarpProduct(funcpizza,funclog);
                Box toycarbox = warpfactory.WarpProduct(functoycar,funclog);
                Console.WriteLine(pizzabox.Product.Name);
                Console.WriteLine(toycarbox.Product.Name);
            }
        }
    

    结果:

    委托使用注意事项:

  • 相关阅读:
    Java 蓝桥杯 算法训练 貌似化学
    Java 蓝桥杯 算法训练 貌似化学
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    JAVA-蓝桥杯-算法训练-字符串变换
    Ceph:一个开源的 Linux PB 级分布式文件系统
    shell 脚本监控程序是否正在执行, 如果没有执行, 则自动启动该进程
  • 原文地址:https://www.cnblogs.com/maomaodesu/p/11659834.html
Copyright © 2011-2022 走看看