一、简单工厂
简单工厂模式的工厂类一般是使用静态方法,通过接收的参数不同来返回不同的对象实例。不修改代码的话,是无法进行动态扩展的。
实例:假设我养了一条狗、一只猫、一头猪,我现在要这三个动物都发出叫声。
1.按照正常的面向对象实现的话,我们会定义狗类、猫类、猪类,实现“叫”的方法;然后在程序中实例化每个对象,调用“叫”方法。因为这个实现比较基础,我就不贴代码了。
2.本块要分享的是简单工厂设计模式的具体实现,下面进入正题。
2.1.1 UML关系类图如下:
2.1.2 我们根据要定义1中提到的猫、狗、猪类,为了使程序更具有统一和扩展性,我们先抽象出一个基类(Animal类),并定义一个虚方法“Call()”
1 public class Animal 2 { 3 public virtual void Call() 4 { 5 Console.WriteLine("我只是抽象动物,并不会叫!"); 6 } 7 }
2.1.3 然后我们依次定义对应的三个类,并重写父类的方法“Call()”
1 class Cat:Animal 2 { 3 public Cat() 4 { 5 6 Console.WriteLine("我是机器猫,我就这样出生了!"); 7 } 8 9 public override void Call() 10 { 11 Console.WriteLine("喵~喵~"); 12 } 13 }
1 class Pig:Animal 2 { 3 public Pig() 4 { 5 Console.WriteLine("我是小猪佩奇,我就这样出生了!"); 6 } 7 public override void Call() 8 { 9 Console.WriteLine("哼~哼~"); 10 } 11 }
1 class Dog:Animal 2 { 3 public Dog() 4 { 5 Console.WriteLine("我是小狗旺财,我就这样出生了!"); 6 } 7 public override void Call() 8 { 9 Console.WriteLine("旺~旺~"); 10 } 11 }
2.1.4 (简单工厂核心)然后重要的一步是我们创建简单工厂类(EasyFactory),并定义创建不同动物实例的方法“CreatAnimal()”,该方法具有输入参数,方法内部根据该参数创建对应的动物实例。
值得注意的是我们方法体定义的是父类Animal类型,内部返回的是子类类型,其主要运用的是面向对象的基础特性(多态)。
1 public class EasyFactory 2 { 3 public enum AnimalType 4 { 5 Cat = 0, 6 Pig = 1, 7 Dog = 2, 8 }; 9 public Animal CreateAnimal(AnimalType AnimalType) 10 { 11 switch (AnimalType) 12 { 13 case AnimalType.Cat: return new Cat();//如果输入参数代表 猫,那么创建猫的实例 14 case AnimalType.Pig: return new Pig();//如果输入参数代表 猪,那么创建猪的实例 15 case AnimalType.Dog: return new Dog();//如果输入参数代表 狗,那么创建狗的实例 16 default: return new Animal(); 17 } 18 19 } 20 21 22 }
2.1.5 开始利用简单工厂创建对应实例,并调用“Call()”方法
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 EasyFactory factory = new EasyFactory();//创建简单工厂的实例 6 7 Animal cat = factory.CreateAnimal(EasyFactory.AnimalType.Cat);//利用简单工厂获取到猫的实例 8 cat.Call();//猫叫 9 10 Animal pig = factory.CreateAnimal(EasyFactory.AnimalType.Pig); 11 pig.Call();//猪叫 12 13 Animal dog = factory.CreateAnimal(EasyFactory.AnimalType.Dog); 14 dog.Call();//狗叫 15 16 17 18 Console.ReadKey(); 19 20 } 21 }
2.1.6 测试程序结果
3 个人总结
简单工厂的优点:客户端不需要承担产品对象的创建责任,简单工厂模式通过这种做法实现了对责任的分割。
简单工厂的缺点:简单工厂将所有的产品创建全部集中在了一起,严格来说违反了单一职责;对于后期的产品增删,简单工厂也要随之修改,违背了开闭原则。
二、工厂模式
上面我们学习的是简单工厂,它虽然解决了部分创建实例的问题,但是不能很好的解决程序扩展问题,违背了程序设计的基本原则。
下面我们引入工厂模式,工厂模式是相对简单工厂模式创建实例的不同解决方案。
实例:假设我养了一条狗、一只猫、一头猪,我现在要这三个动物都发出叫声。
1.按照简单工厂的设计模式来看,与程序设计的基本原则相违背,主要是“单一职责”、“开闭原则”等。
2.下面继续分享关于工厂模式的具体思路和实现。
2.1.1 UML关系图如下:
2.1.2 (工厂模式核心)工厂模式的主要特点是将产品工厂化,即每一个产品都对应一个工厂类用于创建对应产品;那么我们依次创建猫工厂(FactoryCat)、狗工厂(FactoryDog)、猪工厂(FactoryPig)
为了使程序统一、具有可扩展性,我们需要抽象出工厂类的的定义(使上面的工厂类都继承此接口),并定义一个创造动物的接口方法CreatAnimal()。
1 public interface Factory 2 { 3 Animal CreatAnimal(); 4 }
1 class FactoryCat:Factory 2 { 3 4 public Animal CreatAnimal() //这个是造猫工厂方法 5 { 6 return new Cat(); 7 } 8 9 }
1 class FactoryDog : Factory 2 { 3 public Animal CreatAnimal() //这个是造狗工厂方法 4 { 5 return new Dog(); 6 } 7 }
1 class FactoryPig : Factory 2 { 3 public Animal CreatAnimal() //这个是造猪工厂方法 4 { 5 return new Pig(); 6 } 7 }
2.1.3 客户端调用工厂类
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 7 Factory factorycat = new FactoryCat();//创建猫工厂 8 Animal cat = factorycat.CreatAnimal();//用猫工厂创造猫实例 9 cat.Call();//猫叫 10 11 Factory factorydog = new FactoryDog(); 12 Animal dog = factorydog.CreatAnimal(); 13 dog.Call(); 14 15 Factory factorypig = new FactoryPig(); 16 Animal pig = factorypig.CreatAnimal(); 17 pig.Call(); 18 19 Console.ReadKey(); 20 21 } 22 }
2.1.4 程序调试输出如图
3 个人总结
优点:和简单工厂相比,工厂模式的结构更分散,单一职责划分更清楚(符合单一职责原则),新增产品的时候可以直接增加对应工厂类、实现工厂接口(符合开闭原则);很巧妙的使用多态完成整个结构的设计,逻辑比较清晰。
缺点:当产品过多的时候,工厂类过于繁多,造成代码结构庞大;工厂抽象层的加入使得理解难度加大。