简单工厂模式(Simple Factory Pattern)
定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
在简单工厂模式中用于被创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法(Static Factory Method)
需要什么,只需要传入一个正确的参数,就可以获取所需要的对象,而无需知道其实现过程
例如,我开一家披萨店,当客户需要某种披萨并且我这家店里也能做的时候,我就会为其提供所需要的披萨(当然是要钱的哈哈),如果其所需的我这没有,则是另外的情况,后面会谈。这时候,我这家 披萨店就可以看做工厂(Factory),而生产出来的披萨被成为产品(Product),披萨的名称则被称为参数,工厂可以根据参数的不同返回不同的产品,这就是简单工厂模式
简单工厂模式的结构与实现
结构:
Factory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
Product(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
ConcreteProduct(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法(有关抽象类)
实现
1 abstract class Product 2 { 3 public void MethName() 4 { 5 //公共方法的实现 6 } 7 public abstract void MethodDiff(); 8 //声明抽象业务方法 9 }10 class ConcreteProductA : Product11 {12 public override void MethodDiff()13 {14 //业务方法的实现15 }16 }17 18 class Factory19 { 20 public static Product GetProduct(string arg)21 {22 Product product = null;23 if(arg.Equals("A")24 {25 product = new ConcreteProductA();26 //init27 }28 else if(arg.Equals("B"))29 {30 product = new ConcreteProductB();31 //init32 }33 else34 {35 ....//其他情况36 }37 return product;38 }39 }40 41 class Program42 {43 static void Main(string[] args)44 {45 Product product;46 product = Factory.GetProduct("A");//工厂类创建对象47 Product.MethName();48 product.MethodDiff();49 }50 }
简单工厂模式的简化
为了简化简单工厂模式,将抽象产品类和工厂类合并,将静态工厂方法移到抽象产品类中
客户端可以调用产品父类的静态工厂方法,根据不同的参数创建不同类型的产品子类对象。
简单工厂模式的优缺点和适用环境
简单工厂模式的优点
(1)工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责
(2)客户端无需知道所创建具体产品的类名,只需知道参数即可
(3)也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。(这也是我在开始的披萨店里遇到没有的披萨的解决情况)
简单工厂模式的缺点
(1)工厂类集中了所有产品的创建逻辑,职责过重,一旦异常,整个系统将受影响
(2)使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
(3)系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
(4)简单工厂模式使用了static工厂方法,造成工厂角色无法形成基于继承的等级结构。
简单工厂模式的适用环境
(1)工厂类负责创建对的对象比较少,因为不会造成工厂方法中的业务逻辑过于复杂
(2)客户端只知道传入工厂类的参数,对如何创建对象不关心
简单案例
题目:
使用简单工厂模式设计一个可以创建不同几何图形(Shape),如Circle,Rectangle,Triangle等绘图工具类,每个几何图形均具有绘制Draw()和擦除Erase()两个方法
要求在绘制不支持的几何图形时,抛出一个UnsuppShapeException异常,绘制类图并使用C#语言实现。UML:
-
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 /*使用简单工厂模式设计一个可以创建不同几何图形(Shape),如Circle,Rectangle,Triangle等绘图工具类,每个几何图形均具有绘制Draw()和擦除Erase()两个方法 6 * 要求在绘制不支持的几何图形时,抛出一个UnsuppShapeException异常,绘制类图并使用C#语言实现。 7 */ 8 9 namespace SimpleShapeFactory 10 { 11 public interface InShape//图形接口 抽象产品类 12 { 13 void Draw(); 14 void Erase(); 15 } 16 17 public class Circle : InShape//圆形类,具体产品类 18 { 19 private static int count; //生成图形计数 20 string radious; 21 public Circle()//构造 22 { 23 Console.WriteLine("Create Circle"); 24 Console.WriteLine("Input the radious of Circle:"); 25 radious = Console.ReadLine(); 26 } 27 public void Draw()//实现接口方法 28 { 29 int Radious = int.Parse(radious); 30 Console.WriteLine("Display circle " + (++count) +" information:"); 31 Console.WriteLine("Circle "+ count+ " circumference:" + 2 * Radious * 3.14159); 32 Console.WriteLine("Circle "+ count+" area:" + 3.14159 * Radious * Radious); 33 } 34 public void Erase()//实现接口方法 35 { 36 while (true) 37 { 38 Console.WriteLine("Erase current shape(y/n)?"); 39 string choose; 40 choose = Console.ReadLine(); 41 if (choose.Equals("y") || choose.Equals("Y")) 42 { 43 Console.WriteLine("Erase Circle "+count +" successfully!"); 44 count--; 45 break; 46 } 47 else if (choose.Equals("n") || choose.Equals("N")) 48 { 49 Console.WriteLine("Circle "+ count+" successfully saved!"); 50 break; 51 } 52 else 53 { 54 Console.WriteLine("Input error, re-enter!"); 55 } 56 } 57 } 58 } 59 60 class Rectangle : InShape//矩形类,具体产品类 61 { 62 private static int count = 0;//生成图形计数 63 string length; 64 string wideth; 65 public Rectangle()//构造 66 { 67 Console.WriteLine("Create Rectangle"); 68 Console.WriteLine("Input the length and wideth of Rectangle:"); 69 length = Console.ReadLine(); 70 wideth = Console.ReadLine(); 71 } 72 public void Draw()//实现接口方法 73 { 74 int Length = int.Parse(length); 75 int Wideth = int.Parse(wideth); 76 Console.WriteLine("Display rectangle " + (++count) + " information:"); 77 Console.WriteLine("Rectangle "+ count + "circumference:" + 2 * Length * Wideth); 78 Console.WriteLine("Rectangle "+ count + "area:" + Length * Wideth); 79 80 } 81 public void Erase()//实现接口方法 82 { 83 while (true) 84 { 85 Console.WriteLine("Erase current shape(y/n)?"); 86 string choose; 87 choose = Console.ReadLine(); 88 if (choose.Equals("y") || choose.Equals("Y")) 89 { 90 Console.WriteLine("Erase rectangle "+count+ "successfully!"); 91 --count; 92 break; 93 } 94 else if (choose.Equals("n") || choose.Equals("N")) 95 { 96 Console.WriteLine("Rectangle "+ count+" successfully saved!"); 97 break; 98 } 99 else100 {101 Console.WriteLine("Input error, re-enter!");102 }103 } 104 }105 }106 107 class Triangle : InShape//三角形类,具体产品类108 {109 private static int count = 0;//生成图形计数110 string lengtha;111 string lengthb;112 string lengthc;113 public Triangle()//构造114 {115 Console.WriteLine("Create Triangle");116 Console.WriteLine("Input the lengtha ,lengthb and lengthc of Triangle:");117 lengtha = Console.ReadLine();118 lengthb = Console.ReadLine();119 lengthc = Console.ReadLine();120 121 }122 public void Draw()//实现接口方法123 {124 int Lengtha = int.Parse(lengtha);125 int Lengthb = int.Parse(lengthb);126 int Lengthc = int.Parse(lengthc);127 if ((Lengtha + Lengthb > Lengthc) && (Lengtha + Lengthc > Lengthb) && (Lengthb + Lengthc > Lengtha))128 {129 double S = (Lengtha + Lengthb + Lengthc) * 0.5;130 double area = Math.Sqrt(S * (S - Lengtha) * (S - Lengthb) * (S - Lengthc));131 Console.WriteLine("Display triangle "+ (++count)+" information:");132 Console.WriteLine("Triangle " + count +" circumference:" + (Lengtha + Lengthb + Lengthc));133 Console.WriteLine("Triangle "+ count +" area:" + area);134 Erase();135 }136 else137 {138 Console.WriteLine("Create triangle failed!");139 }140 }141 public void Erase()//实现接口方法142 {143 while (true)144 {145 Console.WriteLine("Erase shape(y/n)?");146 string choose;147 choose = Console.ReadLine();148 if (choose.Equals("y") || choose.Equals("Y"))149 {150 Console.WriteLine("Erase tirangle " +count +" successfully!");151 --count;152 break;153 }154 else if (choose.Equals("n") || choose.Equals("N"))155 {156 Console.WriteLine("Triangle "+ count +" successfully saved!");157 break;158 }159 else160 {161 Console.WriteLine("Input error, re-enter!");162 }163 } 164 }165 }166 167 class ShapeFactory//图形工厂类,充当工厂类168 {169 public static InShape Getshape(string type)//静态工厂方法170 {171 InShape shape;172 shape = null;173 if (type.Equals("Circle"))174 {175 shape = new Circle();176 Console.WriteLine("Init set Circle");177 shape.Draw();178 shape.Erase();179 }180 else if(type.Equals("Rectangle"))181 {182 shape = new Rectangle();183 Console.WriteLine("Init set Rectangle");184 shape.Draw();185 shape.Erase();186 }187 else if (type.Equals("Triangle"))188 {189 shape = new Triangle();190 Console.WriteLine("Init set Triangle");191 shape.Draw();192 193 }194 else//异常 这里我应该声明调用异常处理类的,那样会更好些195 {196 Console.WriteLine("UnsupportShapeException!");197 Console.WriteLine("Emotional reminders :Pay 1 million$ to Alipay:132****6151 can create every shape you want!!! ");198 }199 return shape;200 }201 }202 203 class Program//客户端测试类204 {205 static void Main(string[] args)206 {207 while (true)208 {209 InShape shape;210 Console.WriteLine("Please input the shape you want to create");211 string str = Console.ReadLine();212 shape = ShapeFactory.Getshape(str);//通过静态工厂方法创建产品213 Console.ReadLine();214 }215 }216 }217 }
运行结果: