简单工厂模式、工厂方法模式、抽象工厂模式

21 篇文章 0 订阅
18 篇文章 3 订阅

简单工厂模式:创建型模式

   也叫静态工厂模式,它是用来实例化目标类的静态类。一个Simple Factory生产成品,而对客户端隐藏产品生产的细节,实际上是定义一个产品接口,并透过特定静态方法来建立成品。
   就是由一个工厂类根据传入的参数决定创建出哪一种产品类的实例。一个工厂类封装了所有类的实例化。在程序设计中不涉及到具体子类,达到封装效果,也就减少错误修改的机会;如:具体事情做的越多,越容易犯错误,相反,官做得越高,说出的话越抽象,犯错误的可能性就越少。

   简单工厂模式根据提供给它的数据,返回几个可能类中的一个类的实例,通常它返回的类都有一个共同的父类和共同的方法,但每个方法执行的任务不同,而且根据不同的数据进行了优化;专门负责将大量有共同接口的类实例化,而且不必事先知道每次实例化哪一个类。简单工厂模式实际上不属于23个GoF模式,但可以作为学习工厂方法模式的引导。

简单工厂模式的结构:

  工厂类角色:工厂类在客户端的直接控制下创建产品对象。
  抽象产品角色:定义简单工厂创建的对象的父类或它们共同拥有的接口。可以是一个类、抽象类或接口。
  具体产品角色:定义工厂具体加工出的对象。

示例:

class Product
    {

    }

    class ProductA : Product
    {
        public ProductA()
        {
            Console.WriteLine("ProductA类型对象");
        }
    }

    class ProductB : Product
    {
        public ProductB()
        {
            Console.WriteLine("ProductB类型对象");
        }
    }

    /// <summary>
    /// 简单工厂类,知道对象创建的细节,新增加产品时,需要修改此类,违反“开闭原则”,与产品对象的具体类耦合度高,不利于扩展
    /// </summary>
    class Factory
    {
        /// <summary>
        /// 根据传入的参数创建对象,在后期扩展时,需要修改此方法
        /// </summary>
        /// <param name="productName"></param>
        /// <returns></returns>
        public static Product CreateProduct(string productName)
        {
            switch (productName)
            {
                case "A":
                    return new ProductA();

                case "B":
                    return new ProductB();
            }

            return null;
        }
    }

 

工厂方法模式:创建型模式

    在软件系统中,经常面临“某个对象”的创建工作,由于需求的变化,这个对象(具体实现)经常面临剧烈变化,但它却有比较稳定的接口。如何应对?有没有一种封装机制来隔离这种变化,从而保持系统中“其它依赖该对象的对象”不随着需求的变化而变化呢?这就是要说的FactoryMethod模式了。
    定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使得一个类的实例化延迟到子类。

 

使用接口方式实现工厂方法模式,示例:

class Product
    {

    }

    class AppleProduct : Product
    {
        public AppleProduct()
        {
            Console.WriteLine("AppleProduct类型对象");
        }
    }

    class PearProduct : Product
    {
        public PearProduct()
        {
            Console.WriteLine("PearProduct类型对象");
        }
    }

    class CarProduct : Product
    {
        public CarProduct()
        {
            Console.WriteLine("CarProduct类型对象");
        }
    }

    class AirplaneProduct : Product
    {
        public AirplaneProduct()
        {
            Console.WriteLine("AirplaneProduct类型对象");
        }
    }

    /// <summary>
    /// 工厂创建产品对象的方法接口
    /// </summary>
    interface IProductFactoryable
    {
        /// <summary>
        /// 创建产品对象
        /// </summary>
        /// <returns></returns>
        Product CreateProduct(string productName);
    }

    /// <summary>
    /// 生产水果的工厂,可以扩展工厂
    /// </summary>
    class FruitFactory : IProductFactoryable
    {
        /// <summary>
        /// 根据传入的参数创建对象,在后期扩展时,需要修改此方法
        /// </summary>
        /// <param name="productName"></param>
        /// <returns></returns>
        public Product CreateProduct(string productName)
        {
            switch (productName)
            {
                case "Apple":
                    return new AppleProduct();

                case "Pear":
                    return new PearProduct();
            }

            return null;
        }
    }

    /// <summary>
    /// 生产交通工具的工厂,可以扩展工厂
    /// </summary>
    class TrafficFactory : IProductFactoryable
    {
        /// <summary>
        /// 根据传入的参数创建对象,在后期扩展时,需要修改此方法
        /// </summary>
        /// <param name="productName"></param>
        /// <returns></returns>
        public Product CreateProduct(string productName)
        {
            switch (productName)
            {
                case "Car":
                    return new CarProduct();

                case "Airplane":
                    return new AirplaneProduct();
            }

            return null;
        }
    }

 使用抽象类方式实现工厂方法模式,示例:

class Product
    {

    }

    class AppleProduct : Product
    {
        public AppleProduct()
        {
            Console.WriteLine("AppleProduct类型对象");
        }
    }

    class PearProduct : Product
    {
        public PearProduct()
        {
            Console.WriteLine("PearProduct类型对象");
        }
    }

    class CarProduct : Product
    {
        public CarProduct()
        {
            Console.WriteLine("CarProduct类型对象");
        }
    }

    class AirplaneProduct : Product
    {
        public AirplaneProduct()
        {
            Console.WriteLine("AirplaneProduct类型对象");
        }
    }

    /// <summary>
    /// 工厂创建产品对象抽象类
    /// </summary>
     abstract class ProductFactory
    {
        //工厂方法创建产品对象
        public Product MethodFactory( string productName)
        {
            return this.CreateProduct(productName);
        }
        /// <summary>
        /// 创建产品对象
        /// </summary>
        /// <returns></returns>
       protected abstract Product CreateProduct(string productName);
    }



    /// <summary>
    /// 生产水果的工厂,可以扩展工厂
    /// </summary>
    class FruitFactory : ProductFactory
    {
        /// <summary>
        /// 根据传入的参数创建对象,在后期扩展时,需要修改此方法
        /// </summary>
        /// <param name="productName"></param>
        /// <returns></returns>
        protected override Product CreateProduct(string productName)
        {
            switch (productName)
            {
                case "Apple":
                    return new AppleProduct();

                case "Pear":
                    return new PearProduct();
            }

            return null;
        }
    }

    /// <summary>
    /// 生产交通工具的工厂,可以扩展工厂
    /// </summary>
    class TrafficFactory : ProductFactory
    {
        /// <summary>
        /// 根据传入的参数创建对象,在后期扩展时,需要修改此方法
        /// </summary>
        /// <param name="productName"></param>
        /// <returns></returns>
        protected override Product CreateProduct(string productName)
        {
            //Print();
            switch (productName)
            {
                case "Car":
                    return new CarProduct();

                case "Airplane":
                    return new AirplaneProduct();
            }       

            return null;
        }

        private void Print()
        {
            Console.WriteLine("打印飞机");
        }
    }

调用:

class Program
    {
        static void Main(string[] args)
        {
            //简单工厂模式
            //Product pp = Factory.CreateProduct("A");
            //Console.WriteLine(pp.GetType().Name);
            //pp = Factory.CreateProduct("B");
            //Console.WriteLine(pp.GetType().Name);

            //工厂方法模式一
            //IProductFactoryable fac = new FruitFactory();
           // Product fruit=fac.CreateProduct("Apple");
            //Console.WriteLine(fruit.GetType().Name);
            // fruit = fac.CreateProduct("Pear");
            // Console.WriteLine(fruit.GetType().Name);

            //工厂方法模式二
            ProductFactory fac = new FruitFactory();
            Product fruit = fac.MethodFactory("Apple");
            Console.WriteLine(fruit.GetType().Name);
            fruit = fac.MethodFactory("Pear");
            Console.WriteLine(fruit.GetType().Name);

            ProductFactory fac1 = new TrafficFactory();
            Product traffic = fac1.MethodFactory("Car");
            Console.WriteLine(traffic.GetType().Name);
            traffic = fac1.MethodFactory("Airplane");
            Console.WriteLine(traffic.GetType().Name);

            Console.Read();
        }
    }

 

简单工厂模式的不足

    在简单工厂中,只提供了一个工厂类,该工厂类处于对产品类进行实例化的中心位置,它知道每一个产品对象的创建细节,并决定实例化哪一个产品类。简单工厂模式最大的缺点就是当有新产品要加入到系统中时,必须修改工厂类,加入必要的逻辑,这违背了“开闭原则”;在简单工厂模式中,所有的产品都是由同一个工厂创建,工厂类职责较重,业务逻辑复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好的解决这一问题。

工厂方法模式的优缺点:

   优点:在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无需关心创建细节,甚至无须知道具体产品类的类名。
   基于工厂角色和产品角色的多态性设计是工厂方法模式的关键,它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部;工厂方法模式之又称为多态工厂模式,是因为所有的具体工厂类都具有同一个抽象父类。
   使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂类和抽象产品类提供的接口,也无须修改其它的具体工厂类和产品类,而只要添加一个具体工厂和具体产品就可以了;这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

缺点:在添加新品时,需要编写新的具体产品类及与之对应的工厂类,系统中类的个数将成对增加,在一定程序上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。由于考虑到系统的扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

工厂方法适用场景:

   一个类不知道它所需要的具体对象类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品对象的工厂类。

   一个类通过其子类来指定创建个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定创建哪个对象,利用面向对象的多态性和里氏替换原则,在程序运行时,子类对将覆盖父类对象,从而使得系统更易扩展。

   将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

 

抽象工厂模式:(创建型模式)

动机:

在软件系统中经常面临着“一系列相互依赖对象”的创建工作,由于需求变化,往往存在更多系列对象的创建工作;如何应对这种变化?如何提供一种“封闭机制”来避免客户端程序和这种多系列具体对象创建工作的紧耦合?

要点:

如果没有应对多系列对象创建的需求变化,则没有必要使用使用抽象工厂模式,使用简单工厂或静态工厂即可;其主要应用于应对“新系列”需求的变动,缺点在于难以应对“新对象”的需求变动;抽象工厂模式经常与工厂方法模式共同组合来应对对象创建的需求变化。

示例:
在这里插入图片描述

  1. 创建获取鼠标信息共同接口
   public class LenoveMouse : IMouse
    {
        public string GetMouseInfo()
        {
            return "联想品牌鼠标";
        }
    }
  1. 联想鼠标实现类
 public string GetMouseInfo()
        {
            return "联想品牌鼠标";
        }

3.惠普鼠标实现类

  public class HPMouse : IMouse
    {
        public string GetMouseInfo()
        {
            return "惠普品牌鼠标";
        }
    }
    

4.创建键盘接口类

 public interface IKeyboard
    {
         string GetKeyboardInfo();    
    }

5.创建惠普键盘实现类

  public class HPKeyboard : IKeyboard
    {
        public string GetKeyboardInfo()
        {
            return "惠普键盘";
        }
    }

6.创建联想键盘实现类


    public class LenoveKeyboard : IKeyboard
    {
        public string GetKeyboardInfo()
        {
            return "联想键盘";
        }
    }

7.创建工厂接口类提供获取鼠标鼠标和键盘接口

 public interface Factory
    {
        /// <summary>
        /// 获取鼠标工厂
        /// </summary>
        /// <returns></returns>
         IMouse GetMouseFactory();
        /// <summary>
        /// 获取键盘工厂
        /// </summary>
        /// <returns></returns>
        IKeyboard GetKeyboardFactory();

    }

8.创建联想工厂实现类

  public class LenoveFactory : Factory
    {
        public IKeyboard GetKeyboardFactory()
        {
            return new LenoveKeyboard();
        }

        public IMouse GetMouseFactory()
        {
            return new LenoveMouse();
        }
    }

9.创建惠普工厂实现类型

  public class HPFactory:Factory
    {
        public IKeyboard GetKeyboardFactory()
        {
            return new HPKeyboard();
        }

        public IMouse GetMouseFactory()
        {
            return new HPMouse();
        }
    }

控制台调用

   class Program
    {
        static void Main(string[] args)
        {
            //实例化惠普鼠标工厂
            Factory factory = new HPFactory();
            string mouseInfo1 = factory.GetMouseFactory().GetMouseInfo();
            string keyboard1 = factory.GetKeyboardFactory().GetKeyboardInfo();

            //输出惠普鼠标品牌
            Console.WriteLine(mouseInfo1);
            //输出惠普键盘
            Console.WriteLine(keyboard1);
            //实例化联想鼠标工厂
            Factory factory2 = new LenoveFactory();
            string mouseInfo2 = factory2.GetMouseFactory().GetMouseInfo();
            //输出联想鼠标品牌
            Console.WriteLine(mouseInfo2);
            //输出联想键盘品牌
            string keyboard2= factory2.GetKeyboardFactory().GetKeyboardInfo();
            Console.ReadLine();
        }
    }

抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值