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

    结果:

    委托使用注意事项:

  • 相关阅读:
    Python 元类
    Rsync 基础配置
    linux shell find
    找最大的目录
    云主机的上下行带宽
    关于c3p0 ResourcePoolException: Attempted to use a closed or broken resource pool
    recover_file
    MegaCli 监控raid状态
    influxdb
    在Ubuntu 16.04如何安装Java使用apt-get的
  • 原文地址:https://www.cnblogs.com/maomaodesu/p/11659834.html
Copyright © 2011-2022 走看看