设计模式(2):工厂方法模式(Factory Method Pattern)

来源:互联网 发布:数据恢复大师官网 编辑:程序博客网 时间:2024/05/16 06:02

1.接着简单工厂模式谈起

在简单工厂模式(静态工厂模式)中,有一个负责创建对象的工厂类,在这个工厂类里负责所有对象的创建,为了根据用户的不同需求创建不同的对象,工厂类需要进行检查与判断:

public class ListFactory {    public static List createList(String which) {        if(which.equals("ArrayList")) return new ArrayList();        else if(which.equals("LinkedList")) return new LinkedList();        else if(which.equals("MagicList")) return new MagicList();        else //oops, no Concrete List you want    }}

在介绍简单工厂模式的时候已经说过,这个模式的缺点就是当增加产品的时候需要修改这个工厂类,这就导致这个模式违背了开-闭原则(所谓的开-闭原则,就是说对扩展开放,对修改关闭)。即,增加新产品的时候,下图中圈出来的部分就要修改了:
这里写图片描述
为了弥补简单工厂模式的这个不足,引入了工厂方法模式(Factory Method Pattern)。

2. 工厂方法模式的结构

为了能够应对将来新产品的增加,我们可以这样考虑,每个工厂类只负责生产一种产品,这样,当增加新的产品的时候,创建一个新的工厂类,这个新的工厂类负责创建这个新的产品。这样就满足了对扩展开放;同时,由于每个工厂类只负责一种产品的生产,原有的工厂类就不需要修改了,满足了对修改关闭。
如果按照这个思路进行的话,那么我们有多少种产品,就需要对应数量的工厂类。如何组织这些工厂类呢?就是使用和简单工厂模式中产品的形式,即有一个抽象工厂,然后有多个具体工厂。也就是说,面相抽象。
这个抽象工厂既可以是接口,也可以是抽象类,这取决于具体的逻辑了。如果所有的产品都需要某个或某些共同的操作的话,使用抽象类就比较好。
下图就是工厂方法模式的结构图:
这里写图片描述
这里面有四个角色,除了简单工厂模式介绍的三种角色外,多了一个抽象工厂的角色。下面是代码框架:
(1)抽象工厂

public interface Factory {    //工厂方法    public Product createProduct();}

(2)具体工厂

public class ConcreteFactory1 implements Factory {    //工厂方法    public Product createProduct() {        return new ConcreteProduct1();    }}public class ConcreteFactory2 implements Factory {    //工厂方法    public Product createProduct() {        return new ConcreteProduct2();    }}

(3)抽象产品

public interface Product {    //something}

(4)具体产品

public class ConcreteProduct1 implements Product {    //something}public class ConcreteProduct2 implements Product {    //something}

这样,客户使用的时候,会是这样:

public class Client {    public static void main(String[] args) {        Factory factory1=new ConcreteFactory1();        Factory factory2=new ConcreteFactory2();        Product product1=factory1.createProduct();//ConcreteProduct1        Product product2=factory2.createProduct();//ConcreteProduct2        //do something    }}

3.举个例子

我们以制作披萨的披萨店为例。披萨店制作披萨,可以看做是一个简单工厂模式。但是当在别的地方开分店的时候,由于不同的地方有不同的风味,那么披萨店也需要有不同的制作披萨的方法。但所有的披萨店还是有相同点的,就是它们都创建披萨。但是披萨连锁店将来的发展可能会更好,也就是说会在被的地方开新的风味的披萨店。为了满足这个需求,就可以使用工厂方法模式。
(1)披萨
不同风味的披萨都是披萨,所以可以创建一个抽象披萨:

public interface Pizza {    public String info();}

现在,我们在New York和Chicago开了两家分店,分别有各自风味的披萨:

public class NewYorkStylePizza implements Pizza {    public String info() {        return "New York style pizza.";    }}public class ChicagoStylePizza implements Pizza {    public String info() {        return "Chicago style pizza.";    }}

以后可能会有新风味的披萨,但是只需要创建新的披萨类并实现Pizza接口就好了。
(2)披萨店
同样,我们定义一个抽象的披萨店(使用接口,抽象类也可以):

public interface PizzaStore {    public Pizza orderPizza();}

现在有两家分店:

public class NewYorkStylePizzaStore implements PizzaStore {    public Pizza orderPizza() {        return new NewYorkStylePizza();    }}public class ChicagoStylePizzaStore implements PizzaStore {    public Pizza orderPizza() {        return new ChicagoStylePizza();    }}

好了,需要订餐的时候就这样:

PizzaStore nyStylePizzaStore=new NewYorkPizzaStore();PizzaStore cgStylePizzaStore=new ChicagoPizzaStore();Pizza nyStylePizza=nyStylePizzaStore.orderPizza();Pizza cgStylePizza=cgStylePizzaStore.orderPizza();//enjoy yourself

然后,如果生意红火,在北京也开了一家分店,制作北京风味的披萨:

public class BeijingStylePizza implements Pizza {    public String info() {        return "Beijing style pizza.";    }}public class BeijingStylePizzaStore implements PizzaStore {    public Pizza orderPizza() {        return new BeijingStylePizza();    }}

然后,在北京就可以这样点餐了:

PizzaStore bjStylePizzaStore=new BeijingStylePizzaStore();Pizza bjStylePizza=bjStylePizzaStore.orderPizza();//enjoy yourself

这样,即使再多风味的分店,只需要创建新的披萨类和新的披萨店类就可以了。

4.Java中的工厂方法模式

Java集合框架中最重要的就是Collection接口。这个接口声明了一个iterator()方法,要求所有实现这个接口的类都实现这个方法并返回一个Iterator对象。所以,这就是一个工厂方法。

参考资料:《Java与模式》,阎宏

0 0
原创粉丝点击