昨天讲了Singleton模式,今天就工厂模式来讲讲。
在面向对象的编程中,工厂模式是一种经常被使用到的模式。在工厂模式里,有一个公共的抽象父类,父类有一组子类实例,还有一个工厂类,创建不同的子类时,把任务交给工厂类,由它选择生成哪个子类实例,即用户只需要传递必要的参数给工厂类就可以了。
工厂模式分3种:
1.简单工厂(Simple Factory)模式;
2.工厂方法(Factory Method)模式,又称多形性工厂(Polymorphic Factory)模式;
3.抽象工厂(Abstract Factory)模式,又称工具箱(Kit或Toolkit)模式。
先来讲下简单工厂模式。
一个简单工厂模式根据所提供的数据返回某个父类的一个子类实例。
为了方便理解,我写了下面的例子:
//父类
abstract class Fruit {
protected String fruitName;
protected int price;
}
//子类
public class Apple extends Fruit {
public Apple()
{
fruitName="Apple";
price=2;
}
}
//子类
public class Pear extends Fruit {
public Pear()
{
fruitName="Pear";
price=1;
}
}
//工厂类
public class Gardener {
public static Fruit getFruit(String fruitName)
{
if (fruitName.equals("apple"))
{
return new Apple();
}
else if (fruitName.equals("pear"))
{
return new Pear();
}
else
{
System.out.println("Not have the fruit!");
System.exit(0);
}
return null;
}
}
//测试类
public class Test {
public static void main(String[] args) {
Fruit f1=Gardener.getFruit("apple");
Fruit f2=Gardener.getFruit("pear");
System.out.println("The price is:");
System.out.println(f1.fruitName+":"+f1.price);
System.out.println(f2.fruitName+":"+f2.price);
}
}
结果如下:
The price is:
Apple:2
Pear:1
看到没?要找水果的话只需告诉园丁 要找的水果名称就可以了,具体怎么找就不用管了,园丁会帮你找到的。
在简单工厂模式中,一个工厂类处于对产品类(父类)实例化的中心位置上,它知道每一个产品(子类),它决定哪一个产品类应当被实例化。这个模式的优点是允许客户端相对独立于产品创建的过程,但是,因为如果有新的产品加入到系统中去,除了增加新产品的实现类,还需要修改工厂类,将必要的逻辑加入到工厂类中。
接下来是工厂方法。
在简单工厂模式内,体现的是大而全,好比由一个大而全的园丁搞定所有的水果。在工厂方法模式中,则是细而多,满足“一个封装最多引入一个可变化的因数”,就是说一个抽象工厂类,可以派生出多个具体工厂类,每个具体工厂类只能创建一个具体产品类的实例。
工厂方法是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定哪一个产品类应当被实例化,它是让工厂实现了抽象的工厂接口,它把具体怎么生产一种东西,放在具体的工厂去实现了,所谓”延迟到子类中实现”,这个决定被交给子类去作。处于工厂方法模式的中心位置上的类甚至都不去接触哪一个产品类应当被实例化这种细节。
在工厂基类中还可以封装生成目标对象所需要的参数变量,在生成工厂子类对象时可以设置这些参数变量,为生成目标对象做好参数准备。通过提供不同的参数变量值来生成不同的工厂子类,这可以通过简单工厂方式实现,在这个简单工厂类中可以实现决策点,只是这个简单工厂返回的还是一个工厂子类,这个工厂子类可以进而生成目标对象。
拿上面的例子来说,有个园丁总管,下面训练了一批小园丁,每个小园丁只管一种水果。你找水果,就直接叫管那种水果的小园丁去,园丁总管甚至可以不知道是哪个小园丁去找水果了。
下面是一些解释性代码:
public interface GardenerDirector {
public Fruit getFruit();
}
public class GardenerOfApple implements GardenerDirector
{
public Fruit getFruit()
{
return new Apple();
}
}
public class GardenerOfPear implements GardenerDirector
{
public Fruit getFruit()
{
return new Pear();
}
}
后面具体再怎么做我就不再写了。
工厂方法模式可以允许系统在不修改工厂类(无论是工厂父类还是工厂子类)的情况下增加新产品,即符合开-闭原则,只要没有包含简单工厂模式的应用。
最后,说说抽象工厂模式。
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态,主要是用来解决具体产品是有几类产品族的问题,所谓产品族,是指位于不同产品等级结构,功能相关联的产品组成的家族。如图:
|
图中一共有四个产品族,分布于三个不同的产品等级结构中。只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一的确定这个产品。
对于上面那个图的理解,是这样理解的:同种产品,处于一个等级结构中,不同的产品是有不同的等级结构的,所以上面有3个等级结构。处于等级结构中同一层的不同产品,就构成一个产品族,所以上面就有4个产品族。
所谓的抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。如果用图来描述的话,如下图:
对于上面我们的理解如下:一个抽象的工厂类,按等级结构产生N(N>=1)个具体工厂类,每个具体工厂类可以创建出与其等级一样的一个产品族中的所有对象。
抽象工厂模式是工厂方法模式的进一步抽象化和推广。在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。
在一个系统的产品有多于一个的产品族,同属于同一个产品族的产品是设计成在一起使用的时候,我们就要用到抽象工厂模式了。
在抽象工厂模式中,将抽象工厂创建产品的方法定义为工厂方法,就可以使得符合开-闭原则。
工厂模式就说到这里,下次有什么心得再加上来。