- 简单工厂模式概述
- 定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
- 在简单工厂模式中用于被创建实例的方法通常为静态(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 : Product 11 { 12 public override void MethodDiff() 13 { 14 //业务方法的实现 15 } 16 } 17 18 class Factory 19 { 20 public static Product GetProduct(string arg) 21 { 22 Product product = null; 23 if(arg.Equals("A") 24 { 25 product = new ConcreteProductA(); 26 //init 27 } 28 else if(arg.Equals("B")) 29 { 30 product = new ConcreteProductB(); 31 //init 32 } 33 else 34 { 35 ....//其他情况 36 } 37 return product; 38 } 39 } 40 41 class Program 42 { 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 else 100 { 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 else 137 { 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 else 160 { 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 }
- 运行结果:
- 自我感觉写的一般般,如有不对的地方,欢迎指正。