构建简单工厂
现在很容易给出简单工厂类。只检测逗号是否存在,然后返回其中的一个类的实例。
csharp
public class NameFactory
{
public NameFactory(){}
public Namer getName(string name)
{
int i=name.IndexOf(",");
if(i>0)
return new LastFirst(name);
else
{
return new FirstFirst(name);
}
}
}
使用工厂
接下来看看怎样把上述部分组合在一起。为了响应Compute把按钮单击事件,用一个NameFactory
实例返回正确的派生类。
csharp
private void btCompute_click(object sender,System.EventArgs e)
{
Namer nm=nameFact.getName(txName.Text);
txFirst.Text=nm.getFrname();
txLast.Text=nm.getLname();
}
然后调用get重方法和getLname方法获得正确拆分的名字。这里不需要知道使用的是哪一
个派生类,工厂为我们提供了这个类,所需要知道的就是它有两个取出()方法。
我们构建了一个简单用户接口,允许用户以两种方式输入名字,然后显示拆分后的名字。
输入一个名字,然后单击Compute按钮,拆分后的名字显示在下面的文本域中。该程序的关键
之处在于Compute方法,它取回输入的文本,获得Namer类的实例,然后显示结果。
这就是简单工厂模式的基本原理。创建了一个抽象工厂,它决定返回哪一个类的实例并将该实
例返回。接下来可以调用那个类实例的方法,但不需要知道具体使用的是哪一个子类,这种方法把
和数据相关的问题与类的其他方法分隔开来。
数学计算中的工厂模式
大多数使用工厂模式的人都认为,工厂模式可以作为简化杂乱的编程类的工具。然而,工厂模
式用在执行数学运算的程序里也是非常合适的。例如,在快速傅里叶变换(FFT)中,下列四个方
程式要对大量的点对重复执午多遍,才能完成转换。根据这些计算结果绘制的图形形状,将下面
匹个方程式组成FFT"Butterfly(蝴蝶)"类的一个实例。四个方程式如下所示:
R1′=R1+R2cos(y)−I2sin(y)R_{1}' = R_{1} + R_{2}\cos(y) - I_{2}\sin(y)R1′=R1+R2cos(y)−I2sin(y) (1)
R2′=R1−R2cos(y)+I2sin(y)R_{2}' = R_{1} - R_{2}\cos(y) + I_{2}\sin(y)R2′=R1−R2cos(y)+I2sin(y) (2)
I1′=I1+R2sin(y)+I2cos(y)I_{1}' = I_{1} + R_{2}\sin(y) + I_{2}\cos(y)I1′=I1+R2sin(y)+I2cos(y) (3)
I2′=I1−R2sin(y)−I2cos(y)I_{2}' = I_{1} - R_{2}\sin(y) - I_{2}\cos(y)I2′=I1−R2sin(y)−I2cos(y) (4)
当角度y为零时,每次遍历数据时,仍然需要多次计算。这种情况下,可将复杂的数学计算
简化为公式(5)~(8):
R1′=R1+R2R_{1}' = R_{1} + R_{2}R1′=R1+R2 (5)
R2′=R1−R2R_{2}' = R_{1} - R_{2}R2′=R1−R2 (6)
I1′=I1+I2I_{1}' = I_{1} + I_{2}I1′=I1+I2 (7)
I2′=I1−I2I_{2}' = I_{1} - I_{2}I2′=I1−I2 (8)
我们先定义一个保存复数的类。
csharp
public class Complex
{
float real;
float imag;
public Complex(float r,float i)
{
real=r;
imag=i;
}
public void setReal(flaot r)
{
real=r;
}
public void setImag(float i)
{
imag=i;
}
public float getReal()
{
return real;
}
public float getImag()
{
return imag;
}
}
基类Butterfly是一个抽象类,任何一个具体类都要填充Execute命令的实现过程。
csharp
public abstract class Bufferfly
{
float y;
public Bufferfly()
{
public Bufferfly(float angle)
{
y=angle;
}
abstract public void Execute(Complex X,Complex y);
}
}
接下来在Butty的基础上创建一个简单的加法类,它实现了公式(5~8)的加法和减法运算
csharp
class AddBufferfly:AddBufferfly
{
float oldr1,old2;
public AddBufferfly(float angle)
{
public override void Execute(Complex xi,Complex xj)
{
oldr1=xi.getReal();
oldi1=xi.getImag();
xi.setReal(oldr1+xj.getReal());
xj.setReal(oldr1- xj.getReal());
xi.setImag(oldi1+xj.getImag());
xj.setImag(oldi1-xj.getImag());
}
}
}
TrigButterny类与此类似,只是Execute方法包含了公式(1)、(4)中的三角函数的计算
csharp
public class TrigButterfly:TrigButterfly{
float y,oldr1,oldi1;
float cosy,siny;
float r2cosy,r2siny,i2cosy,i2siny;
}
public TrigButterfly(float angle)
{
y=angle;
cosy=(float)Math.Cos(y);
siny=(float)Math.Sin(y);
}
public override void Execute(Complex xi,Complex xj)
{
oldr1=xi.getReal();
oldi1=xi.getImag();
r2cosy=xj.getReal()*cosy;
r2siny=xj.getReal()*siny;
i2cosy=xj.getImag()*cosy;
i2siny=xj.getImag()*siny;
xi.setReal(oldr1+r2cosy+i2siny);
xi.setImag(oldi1-r2siny+i2cosy2);
xj.setReal(oldr1-r2cosy-i2siny);
xj.setImag(oldi1+r2siny-i2cosy);
}
然后创建一个简单工厂类,它决定返回哪一个类实例。因为已经创建了类,所以,我
们把T厂类称为Cocoon(茧)。这里不需要实例化Cocoon,所以将它的方法声明为静态的。
csharp
public class Cocoon
{
static public Butterfly getButterfly(float y)
{
if(y!=0)
return new TrigButterfly(y);
else
return new addButterfly(y);
}
}