zoukankan      html  css  js  c++  java
  • 设计模式——工厂模式

    工厂模式

    先来说说现实生活中的工厂。有一个汽车零售商老板,向宝马公司预定了10张宝马,并签订合同,宝马公司前台将这个订单发送给生产宝马汽车的工厂,工厂收到这个订单后开始生产,等生产结束再把车辆交给零售商老板,完成了这个订单。在这过程中,零售商老板只告诉宝马公司他需要的车型,他并不知道这车是通过怎样的方式生产出来的。所谓工厂模式就是创建对象的一种模式,是我们最常用的实例化对象的模式。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给程序带来更大的可扩展性和尽量少的修改量。

    工厂模式有三种分类:简单工厂,工厂方法,抽象工厂。我通过生产汽车来举例。其中有三个类,分别是Car类(轿车类),Bus类(公交车类),Truck类(卡车类),这三个类代表“工厂”可以生产的“产品”。

    class Car     // 轿车类
        {
            public Car()
            {
                Console.WriteLine("生产了一辆轿车!");
            }
        }
    
        class Bus    // 公交车类
        {
            public Bus()
    
            {
               Console.WriteLine("生产了一辆公交车!");
            }
        }
    class Truck // 卡车类 { public Truck() { Console.WriteLine("生产了一辆卡车!"); } }

    先看看简单工厂模式。

    /// <summary>
    /// 简单工厂模式
    /// </summary>
    
    namespace ConsoleApp1   // 命名空间
    {
    /// <summary>
    ///可以在工厂里制造的车型
    /// </summary>
    public enum Cartype
        {
            car,
    
            bus,
    
            truck
        }
        /// <summary>
        ///这是一个类,模拟客户
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                //客户需要让工厂生产一张轿车
    
                object obj = Factory.Create(Cartype.car);  // 客户将参数传递给工厂,让工厂开始生产车辆
    
                Console.WriteLine(obj.GetType());          // 检测车类型
    
                Console.ReadLine();
            }
        }
        /// <summary>
        /// 制造车辆的工厂
        /// </summary>
        public static class Factory
        {
            public static object Create(Cartype cartype)    // 通过枚举类型的参数动态创建对象
            {
                switch (cartype)
                {
                    case Cartype.car:
                        return new Car(); break;
                    case Cartype.bus:
                        return new Bus(); break;
                    case Cartype.truck:
                        return new Truck(); break;
                    default:
                        return null; break;
                }
            }
    }

    说明:以上有2个类,一个是客户类(Program类),包含程序入口main方法,另一个是工厂类(Factory类),通过客户传递的参数进行实例化对象,然后再将“生产”出来的对象return给客户。

    运行结果:

     

    优点:工厂类包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类。对于客户端来说,去除了对具体产品的依赖。
    缺点:不符合开放封闭原则(OCP)。不修改代码的话,是无法进行拓展的(如果增加新的产品,需要增加switch分支)。

     

    接下来简要说说工厂方法,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法将类的实例化延长到子类。在工厂方法中,工厂的接口中只包含一个方法。在此不再展示实现源码。

    来看看这种模式的优点和缺点:

    优点:符合开放封闭原则(OCP),工厂方法模式实现时,客户端需要决定实例化哪个工厂来创建对象。工厂方法把简单工厂的内部创建对象的逻辑判断移到了客户端。如果需要修改,只需要修改客户端即可!

    缺点:但随着产品类的增加,对应的工厂类也会随之增多。

     

    抽象工厂,是应对产品族概念的,比如说,每个汽车公司可能要同时生产轿车,公交车,卡车,那么每一个工厂都要有创建轿车,公交车和卡车的方法。

    /// <summary>
    
    /// 抽象工厂
    
    /// </summary>
    
    namespace ConsoleApp2
    
    {
    
        /// <summary>
    
        /// 客户
    
        /// </summary>
    
        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                Factory_A factory_A = new Factory_A();     // 创建Factory_A(宝马公司)实例
    
                Factory_B factory_B = new Factory_B();      // 创建Factory_B(奔驰公司)实例
    
                //在宝马公司生产车辆
    
                object obj1 = factory_B.CreateBus();    // 在宝马公司生产公交车
    
                Console.WriteLine(obj1.GetType());      // 检测是否是公交车
    
                object obj2 = factory_B.CreateCar();    // 在宝马公司生产轿车
    
                Console.WriteLine(obj2.GetType());     // 检测是否是轿车
    
                object obj3 = factory_B.CraeteTruck(); //在宝马公司生产卡车
    
                Console.WriteLine(obj3.GetType());    // 检测是否是卡车
    
     
    
                // 在奔驰公司生产车辆
    
                object obj4= factory_A.CraeteTruck();  //  在奔驰公司生产卡车
    
                Console.WriteLine(obj4.GetType());    // 检测是否是卡车
    
                object obj5 = factory_A.CreateBus();   // 在奔驰公司生产公交车
    
                Console.WriteLine(obj5.GetType());    // 检测是否是公交车
    
                object obj6 = factory_A.CreateCar();   // 在奔驰公司生产轿车
    
                Console.WriteLine(obj6 .GetType());   // 检测是否是轿车            Console.ReadLine();
    
            }
    
        }
    
        /// <summary>
    
        /// 接口   工厂可以制造的产品
    
        /// </summary>
    
        interface FactoryMethod {
    
            object CreateBus();   // 制造公交车
    
            object CreateCar();   // 制造轿车
    
            object CraeteTruck(); // 制造卡车
    
        }
    
        /// <summary>
    
        /// 宝马公司,继承了FactoryMethod,所以可以制造3种车
    
        /// </summary>
    
        public class Factory_A : FactoryMethod
        {
            public  object CraeteTruck()
            {
                return new Truck();
            }
            public object CreateBus()
            {
                return new Bus();
            }
            public  object CreateCar()
            {
                return  new Car ();
            }
        }
        /// <summary>
        ///奔驰公司,继承了FactoryMethod,所以可以制造3种车
        /// </summary>
        public class Factory_B : FactoryMethod
        {
            public object CraeteTruck()
            {
               return new Truck();
            }
     
            public object CreateBus()
            {
                return new Bus();
            }
            public object CreateCar()
            {
                return new Car();
            }
    }

    运行结果:

     

    工厂模式总结:

    简单工厂:简单实用,但违反开放封闭。

    工厂方法:开放封闭,单一产品。
    抽象工厂:开放封闭,多个产品。

  • 相关阅读:
    Linux系统常用工具集
    Storm安装部署
    Linux下搭建Elasticsearch7.6.2集群
    解决SpringMVC @RequestBody无法注入基本数据类型
    微服务概念
    HashMap的原理简单介绍
    mysql进阶
    vue 路由缓存 keep-alive include和exclude无效
    el-date-picker 时间日期格式,选择范围限制
    RedisTemplate使用rightPushAll往list中添加时的注意事项
  • 原文地址:https://www.cnblogs.com/spiderljx/p/10837903.html
Copyright © 2011-2022 走看看