设计模式(4)--工厂模式

能解决什么样的问题

  假设一种这样的情形,先有个披萨店,里面有各种各样的披萨,每种披萨当然会加不同的调料。当客人来点餐时,直接就会跟服务员说来个xx披萨,或许他还会说少点番茄酱。把这个写成一个java程序,测试时main函数里创建一个披萨,最后打印出披萨信息,你会如何解决呢?

  如果你碰到类似于这样的问题,那么使用工厂模式是一个不错的选择。

如何解决问题

  根据前面所介绍的模式,相信你已经发现了我们应该尽量针对接口编程,而不是针对实现进行编程。

  1.定义一个调料接口Ingredient,所有的调料都实现这个接口,该接口包含一个getName方法

  2.定义一个披萨抽象类Pizza,当然也可以定义成接口,但是定义成接口那么就不能包含属性了,这个选择哪种根据自己的实际需求。所有的具体披萨类都需要实现这个抽象类,这个抽象类中包含属性有String类型的name和List<Ingredient>类型的ingredient,方法有抽象方法add(添加调料)和以实现的方法display(主要是打印出该披萨的名称和调料)。

  3.定义一个工厂接口Factory,其方法有getIngredient,有个参数为name,即为调料名称,主要就是用来添加调料。这里定义一个接口是为了以后便于扩展,如果直接定义一个工厂具体类,以后要是有其他的调料工厂(不同地区所使用的调料可能不一,尽管可能名字一样),那么这时候你就需要修改披萨类中包含了工厂类型了,这样就针对实现进行编程了,极大降低了扩展性。

  4.定义一些具体的工厂类,这里就只定义一个具体工厂类IngredientFactory,实现接口中的方法,根据调料名称生产出不同的调料。

  5.定义一些具体的调料类,如Cheese、Clam、Sauce、Dough等,这些调料都实现Ingredient接口

  6.定义一些具体的Pizza类,如CheesePizza、ClamPizza等,这些类需要继承Pizza这个抽象类,实现其中为实现的方法,当然也需要有个工厂类的属性,这个用来生产调料。

  7.测试这样设计是否可以解决问题

  示例代码如下:

注意以下代码不是一个文件

//Ingredient.java
public interface Ingredient {

    public String getName();
}

//Cheese.java
public class Cheese implements Ingredient {

    private String name;

    public Cheese() {
        name = "Chess";
    }

    @Override
    public String getName() {
        return name;
    }

}

//Clam.java
public class Clam implements Ingredient {

    private String name;

    public Clam() {
        name = "Clam";
    }

    @Override
    public String getName() {
        return name;
    }
}

//Sauce.java
public class Sauce implements Ingredient {
    private String name;

    public Sauce() {
        name = "Sauce";
    }

    @Override
    public String getName() {
        return name;
    }
}

//Factory
public interface Factory {

    public Ingredient getIngredient(String name);

}

//IngredientFactory.java
public class IngredientFactory implements Factory {

    @Override
    public Ingredient getIngredient(String name) {
        if ("cheese".equals(name)) {
            return new Cheese();
        } else if ("clam".equals(name)) {
            return new Clam();
        } else if ("sauce".equals(name)) {
            return new Sauce();
        } else {
            return null;
        }

    }

}

//Pizza.java
import java.util.List;

public abstract class Pizza {

    protected String name;

    protected List<Ingredient> ingredients;

    public void display() {
        System.out.println("pizza name:" + name);
        if (ingredients.size() > 0) {
            System.out.print("ingredients:");
            for (Ingredient ingredient : ingredients) {
                System.out.print(ingredient.getName() + " ");
            }
        }
    }

    public abstract void addIngredient();
}

//CheesePizza.java
import java.util.ArrayList;

public class CheesePizza extends Pizza {
    private Factory ingredientFactory;
    
    public CheesePizza(Factory factory) {
        this.ingredientFactory = factory;
        name = "CheesePizza";
        ingredients = new ArrayList<Ingredient>();
        addIngredient();
    }
    @Override
    public void addIngredient() {
        ingredients.add(ingredientFactory.getIngredient("sauce"));
        ingredients.add(ingredientFactory.getIngredient("cheese"));
    }

}

//ClamPizza.java
import java.util.ArrayList;

public class ClamPizza extends Pizza {

    private Factory ingredientFactory;

    public ClamPizza(Factory factory) {
        name = "ClamPizza";
        this.ingredientFactory = factory;
        ingredients = new ArrayList<Ingredient>();
        addIngredient();
    }

    @Override
    public void addIngredient() {
        ingredients.add(ingredientFactory.getIngredient("sauce"));
        ingredients.add(ingredientFactory.getIngredient("clam"));
    }
}

//测试类 Test.java
public class Test {

    public static void main(String[] args) {
        Pizza pizza = new CheesePizza(new IngredientFactory());

        pizza.display();
    }
}

  自己动手试试吧,我觉你的猜测肯定是对的。

  下一篇将介绍单例模式,如果大家对我的博客有什么见解或疑问可以留言

posted @ 2017-04-27 12:44  逆倒尘光  阅读(192)  评论(0编辑  收藏  举报