简单工厂与工厂方法模式
工厂模式在一些设计模式的书中分为简单工厂模式,工厂方法模式和抽象工厂模式三类。也有把工厂方法模式划分到抽象工厂模式的,认为工厂方法是抽象工厂模式的特例的一种,就是只有一个要实现的产品接口。
工厂模式流程图:
1.简单工厂模式
简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法)。编程中的简单工厂就是一个生产对象的类,它的主要作用是创建具体的产品类实例。专门定义一个类来负责创建其他类的实例
简单工厂模式优缺点:
优点:工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅"消费"产品。简单工厂模式通过这种做法实现了对责任的分割。简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。通过它,外界可以从直接创建具体产品对象的尴尬局面中摆脱出来。外界与具体类隔离开来,偶合性低。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
缺点:当产品有复杂的多层等级结构时,工厂类只有自己,以不变应万变,就是模式的缺点。因为工厂类集中了所有产品创建逻辑,一旦增加产品或者删除产品,整个系统都要受到影响。系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂,违背了"开放–封闭"原则(OCP).另外,简单工厂模式通常使用静态工厂方法,这使得无法由子类继承,造成工厂角色无法形成基于继承的等级结构。简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。
基础类:
public abstract class Operation
{
public int One { get; set; }
public int Two { get; set; }
public Operation(int a, int b)
{
One = a;
Two = b;
}
public abstract int GetResult();
}
加法:
public class OperationAdd : Operation
{
public OperationAdd(int a, int b):base(a,b)
{
}
public override int GetResult()
{
return One + Two;
}
}
减法:
public class OperationSub: Operation
{
public OperationSub(int a,int b):base(a,b)
{
}
public override int GetResult()
{
return One - Two;
}
}
乘法:
public class OperationMul: Operation
{
public OperationMul(int a,int b):base(a,b)
{
}
public override int GetResult()
{
return One * Two;
}
}
除法:
public class OperationDiv: Operation
{
public OperationDiv(int a, int b) : base(a, b)
{
}
public override int GetResult()
{
return One / Two;
}
}
/// <summary>
/// 简单工厂
/// </summary>
public class SimpleFactoryPattern
{
public static Operation GetOperation(string oper, int a, int b)
{
Operation operation = null;
switch (oper)
{
case "+":
operation = new OperationAdd(a, b);
break;
case "-":
operation = new OperationSub(a, b);
break;
case "*":
operation = new OperationMul(a, b);
break;
case "/":
operation = new OperationDiv(a, b);
break;
}
return operation;
}
}
控制台调用:
//简单工厂模式
static void Main(string[] args)
{
Console.WriteLine("请输入你的第一个数字");
int a = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入你的第二个数字");
int b = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入你的运算符");
string str = Console.ReadLine();
Operation oper = SimpleFactoryPattern.GetOperation(str, a, b);
if (oper!=null)
{
int result = oper.GetResult();
Console.WriteLine("{0}{1}{2}={3}",a,str,b, result);
Console.ReadLine();
}
else
{
Console.WriteLine("没有你需要的运算符");
Console.ReadLine();
}
}
2.工厂模式
工厂模式方法是粒度很小的设计模式,因为模式的表现只是一个抽象的方法。提前定义用于创建对象的接口,让子类(具体工厂)决定实例化具体的某一个类,即在工厂和产品中间增加接口(抽象工厂),工厂不再负责产品的创建,由接口针对不同条件返回具体的类实例,由具体类实例(具体工厂)去实现。工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现ocp,实现了可扩展。其次实现更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式是对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
优点:工厂方法模式是为了克服简单工厂模式的缺点(主要是为了满足Open Closed Principle)而设计出来的。简单工厂模式的工厂类随着产品类的增加需要增加很多方法(或代码),而工厂方法模式每个具体工厂类只完成单一任务,代码简洁。工厂方法模式完全满足OCP(开放封闭原则),即它有非常良好的扩展性。
缺点:假如某个具体产品类需要进行一定的修改,很可能需要修改对应的工厂类。当同时需要修改多个产品类的时候,对工厂类的修改会变得相当麻烦。比如说,每增加一个产品,相应的也要增加一个子工厂,会加大了额外的开发量。
抽象一个方法:
public abstract class FactoryPattern
{
//抽象一个方法
public abstract Operation GetOperation(int a, int b);
}
工厂加法:
/// <summary>
/// 工厂加法
/// </summary>
public class FactoryOperationAdd : FactoryPattern
{
public override Operation GetOperation(int a, int b)
{
return new OperationAdd(a, b);
}
}
工厂减法:
/// <summary>
/// 工厂模式减法
/// </summary>
public class FactoryOperationSub:FactoryPattern
{
public override Operation GetOperation(int a, int b)
{
return new OperationSub(a,b);
}
}
工厂乘法:
/// <summary>
/// 工厂模式乘法
/// </summary>
public class FactoryOperationMul : FactoryPattern
{
public override Operation GetOperation(int a, int b)
{
return new OperationMul(a, b);
}
}
工厂除法:
/// <summary>
/// 工厂除法
/// </summary>
public class FactoryOperationDiv: FactoryPattern
{
public override Operation GetOperation(int a, int b)
{
return new OperationDiv(a,b);
}
}
控制台调用:
//工厂模式
static void Main(string[] args)
{
Console.WriteLine("请输入你的第一个数字:");
int a = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入你的第二个数字:");
int b = Convert.ToInt32(Console.ReadLine());
FactoryPattern fac;
Console.WriteLine("请输入你的运算符:");
xuanze:
switch (Console.ReadLine())
{
case "+":
fac = new FactoryOperationAdd();
break;
case "-":
fac = new FactoryOperationSub();
break;
case "*":
fac=new FactoryOperationMul();
break;
case "/":
fac = new FactoryOperationDiv();
break;
default:
Console.WriteLine("输入有误,请重新输入:");
goto xuanze;
}
Operation oper = fac.GetOperation(a, b);
if (oper != null)
{
int result = oper.GetResult();
Console.WriteLine("结果为:");
Console.WriteLine(result);
Console.ReadKey();
}
}