简单工厂模式(Simple Factory Pattern)
程序员文章站
2022-07-02 17:58:15
简单工厂模式概述 简单工厂模式的结构与实现 结构: 实现 1 abstract class Product 2 { 3 public void MethName() 4 { 5 //公共方法的实现 6 } 7 public abstract void MethodDiff(); 8 //声明抽象业务 ......
-
简单工厂模式概述
- 定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父亲
- 在简单工厂模式中用于被创建实例的方法通常为静态(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)也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。(这也是我在开始的披萨店里遇到没有的披萨的解决情况)
2. 简单工厂模式的缺点
(1)工厂类集中了所有产品的创建逻辑,职责过重,一旦异常,整个系统将受影响
(2)使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
(3)系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
(4)简单工厂模式使用了static工厂方法,造成工厂角色无法形成基于继承的等级结构。
3. 简单工厂模式的适用环境
(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 }
- 运行结果:
- 自我感觉写的一般般,如有不对的地方,欢迎指正。