本文共 9458 字,大约阅读时间需要 31 分钟。
一:介绍
顾名思义,工厂模式就是创建产品,在程序设计中称作创建对象实例,属于创建型模式
工厂模式分为简单工厂模式和工厂方法模式,根据工厂的抽象程度工厂方法模式又可以分为工厂方法模式和抽象工厂模式 ——简单工厂模式:将创建实例的过程封装在一个类中 ——工厂方法模式和抽象工厂模式:将创建实例的过程交给具体的产品工厂 ——反射:使用反射机制可以解决简单工厂模式、工厂方法模式和抽象工厂模式的弊端,在使用时舍弃掉是选择哪一种产品还是选择哪一种产品工厂 总之,工厂模式就是将创建实例的操作(new的过程)封装起来,降低耦合度,提高扩展性二:适用场景
三种工厂模式有各自的应用场景,根据实际应用进行选择,无所谓高级与低级
三:不使用工厂模式
例如一个工厂去生产手机
下面是不使用工厂模式的写法:using System;public class MainClass{ public static void Main() { Phone phone = new Apple(); phone.ProductionPhone(); }}public interface Phone{ void ProductionPhone();}public class Apple : Phone{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); }}public class HUAWEI : Phone{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); }}
四:简单工厂模式
不使用工厂模式在访问对象时需要访问到创建实例的逻辑(new HUAWEI(),new Apple()),所以应该考虑封装成一个单独的类来做这个创建实例的过程
下面是使用简单工厂模式的写法:将创建实例的过程封装到一个单独类中去管理using System;public class MainClass{ public static void Main() { Phone phone = Factory.GetPhone("Apple"); phone.ProductionPhone(); }}public interface Phone{ void ProductionPhone();}public class Apple : Phone{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); }}public class HUAWEI : Phone{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); }}////// 将创建实例的过程封装到一个单独类中去管理/// public class Factory{ public static Phone GetPhone(string _phoneType) { switch (_phoneType) { case "Apple": return new Apple(); case "HUAWEI": return new HUAWEI(); } return null; }}
五:工厂方法模式
简单工厂模式将创建实例的过程封装在了一个类中,假如现在需要增加生产小米品牌手机的需求,那么就需要在Factory类的Switch分支中添加小米品牌的判断,这样的话我们不但对扩展开放了,对修改也开放了,违背了开放-封闭原则,所以就有了工厂方法模式
简单工厂模式与工厂方法模式的区别在于简单工厂模式把创建实例的过程封装在了一个类中,而工厂方法模式将创造实例的过程交给了每一个具体实例类的工厂 下面是使用工厂方法模式的写法:将生产具体产品的过程(创造实例)交给具体的产品工厂using System;public class MainClass{ public static void Main() { AbstractFactory appleFactory = new AppleFactory(); Phone apple_phone = appleFactory.GetPhone(); apple_phone.ProductionPhone(); }}public interface Phone{ void ProductionPhone();}public class Apple : Phone{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); }}public class HUAWEI : Phone{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); }}////// 将创造实例的过程交给了每一个具体的产品工厂/// public interface AbstractFactory{ Phone GetPhone();}public class AppleFactory : AbstractFactory{ public Phone GetPhone() { return new Apple(); }}public class HUAWEIFactory : AbstractFactory{ public Phone GetPhone() { return new HUAWEI(); }}
六:抽象工厂模式
假如现在工厂不仅仅生产Phone,还需要生产Watch
下面是使用抽象工厂模式的写法:using System;public class MainClass{ public static void Main() { AbstractFactory appleFactory = new AppleFactory(); Phone apple_phone = appleFactory.GetPhone(); apple_phone.ProductionPhone(); Watch apple_watch = new AppleFactory().GetWatch(); apple_watch.ProductionWatch(); }}public interface Phone{ void ProductionPhone();}public interface Watch{ void ProductionWatch();}public class Apple : Phone, Watch{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); } public void ProductionWatch() { Console.WriteLine("生产苹果手表"); }}public class HUAWEI : Phone, Watch{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); } public void ProductionWatch() { Console.WriteLine("生产华为手表"); }}////// 抽象工厂中增加创建实例的接口/// public interface AbstractFactory{ Phone GetPhone(); Watch GetWatch();}public class AppleFactory : AbstractFactory{ public Phone GetPhone() { return new Apple(); } public Watch GetWatch() { return new Apple(); }}public class HUAWEIFactory : AbstractFactory{ public Phone GetPhone() { return new HUAWEI(); } public Watch GetWatch() { return new HUAWEI(); }}
以上代码虽然满足了需求,但只是增加一个生产Watch的需求,但我们需要访问并修改AbstractFactory、AppleFactory和HEUWEIFactory三个类,相当于对修改也开放了,违背了开放-封闭原则
当需求导致需要增加抽象接口时,推荐使用简单工厂模式 下面是使用简单工厂模式对上面的代码进行改写:只需要增加一个创建Watch对象的静态方法using System;public class MainClass{ public static void Main() { Watch watch = Factory.GetWatch("Apple"); watch.ProductionWatch(); }}public interface Phone{ void ProductionPhone();}public interface Watch{ void ProductionWatch();}public class Apple : Phone, Watch{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); } public void ProductionWatch() { Console.WriteLine("生产苹果手表"); }}public class HUAWEI : Phone, Watch{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); } public void ProductionWatch() { Console.WriteLine("生产华为手表"); }}public class Factory{ public static Phone GetPhone(string _phoneType) { switch (_phoneType) { case "Apple": return new Apple(); case "HUAWEI": return new HUAWEI(); default: return null; } } public static Watch GetWatch(string _watchType) { switch (_watchType) { case "Apple": return new Apple(); case "HUAWEI": return new HUAWEI(); default: return null; } }}
假如现在的需求不是生产Watch,而是新增一个小米的品牌,那么使用简单工厂模式就不太适合了,我们需要改动Factory中的Switch分支,又违背了开放-封闭原则
当需求导致需要增加具体类时,推荐使用抽象工厂模式 下面是使用抽象工厂模式的写法:只需要增加XIAOMIFactory类去创建对象using System;public class MainClass{ public static void Main() { AbstractFactory xiaomiFactory = new XIAOMIFactory(); Phone xiaomi_phone = xiaomiFactory.GetPhone(); xiaomi_phone.ProductionPhone(); }}public interface Phone{ void ProductionPhone();}public class Apple : Phone{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); }}public class HUAWEI : Phone{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); }}public class XIAOMI : Phone{ public void ProductionPhone() { Console.WriteLine("生产小米手机"); }}public interface AbstractFactory{ Phone GetPhone();}public class AppleFactory : AbstractFactory{ public Phone GetPhone() { return new Apple(); }}public class HUAWEIFactory : AbstractFactory{ public Phone GetPhone() { return new HUAWEI(); }}public class XIAOMIFactory : AbstractFactory{ public Phone GetPhone() { return new XIAOMI(); }}
七:通过反射解决创建对象实例的问题(解决选择哪一种产品&选择哪一种产品工厂的弊端)
首先对以上三种工厂模式做个总结: 最好理解的便是简单工厂模式,但当需求是增加具体类时,需要增加Switch分支,违背了开放-封闭原则,所以建议使用工厂方法模式或抽象工厂模式,但工厂方法模式和抽象工厂模式在创建产品工厂时需要决定实例化什么类型的工厂,选择判断的问题仍然存在,可以理解为只不过是把简单工厂模式类内部的选择判断移到了创建产品工厂时进行选择判断
对于以上的不足,使用反射技术可以一并解决(需要引入System.Reflection的命名空间),首先利用反射技术进行改写:\using System;using System.Reflection;public class MainClass{ public static void Main() { Phone phone = Factory.GetPhone(); phone.ProductionPhone(); }}public interface Phone{ void ProductionPhone();}public class Apple : Phone{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); }}public class HUAWEI : Phone{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); }}public class Factory{ //程序集名称 public static string assembly = "Test"; //命名空间.类名 public static string product = "Apple"; public static Phone GetPhone() { return (Phone)Assembly.Load(assembly).CreateInstance(product); }}
假如需要新增一个生产手表的需求,只需在Factory类中增加一个生产Watch对象的方法,代码如下:
using System;using System.Reflection;public class MainClass{ public static void Main() { Watch watch = Factory.GetWatch(); watch.ProductionWatch(); }}public interface Phone{ void ProductionPhone();}public interface Watch{ void ProductionWatch();}public class Apple : Phone, Watch{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); } public void ProductionWatch() { Console.WriteLine("生产苹果手表"); }}public class HUAWEI : Phone, Watch{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); } public void ProductionWatch() { Console.WriteLine("生产华为手表"); }}public class Factory{ public static string assembly = "程序集名称"; public static string product = "Apple"; public static Phone GetPhone() { return (Phone)Assembly.Load(assembly).CreateInstance(product); } public static Watch GetWatch() { return (Watch)Assembly.Load(assembly).CreateInstance(product); }}
假如不需要生产手表了,而是新增一个小米的品牌,按照之前的写法,如果使用简单工厂模式则需要增加Switch分支,如果使用抽象工厂模式则需要新增一个小米工厂类,如下图所示
但归根结底不管是什么品牌的手机,最终都返回Phone类对象,某种意义上来说造成了代码的重复,如果使用反射技术的话代码就简洁多了,我们只需要修改product字段即可,代码如下:using System;using System.Reflection;public class MainClass{ public static void Main() { Phone phone = Factory.GetPhone(); phone.ProductionPhone(); }}public interface Phone{ void ProductionPhone();}public class Apple : Phone{ public void ProductionPhone() { Console.WriteLine("生产苹果手机"); }}public class HUAWEI : Phone{ public void ProductionPhone() { Console.WriteLine("生产华为手机"); }}public class XIAOMI : Phone{ public void ProductionPhone() { Console.WriteLine("生产小米手机"); }}public class Factory{ public static string assembly = "程序集名称"; public static string product = "XIAOMI"; public static Phone GetPhone() { return (Phone)Assembly.Load(assembly).CreateInstance(product); }}
转载地址:https://liuhaowen.blog.csdn.net/article/details/104186250 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!