工厂模式

2018-01-08  本文已影响14人  imyyq_star

需求

开披萨店,披萨有很多种,披萨店也可以有很多个分店

目的

对修改关闭,针对接口编程,不针对实现编程

简单工厂

披萨

public abstract class Pizza
{
    String name;
    String dough;// 面团
    String sauce;// 酱
    ArrayList<String> toppings = new ArrayList<String>();// 浇在披萨上的

    public String getName()
    {
        return name;
    }

    // 准备
    public void prepare()
    {
        System.out.println("Prepare " + name);
        System.out.println("Tossing dough...");
        System.out.println("Adding sauce...");
        System.out.println("Adding toppings: ");
        for (String topping : toppings)
        {
            System.out.println("   " + topping);
        }
    }

    // 烘烤
    public void bake()
    {
        System.out.println("Baking " + name);
    }

    // 切片
    public void cut()
    {
        System.out.println("Cutting " + name);
    }

    // 打包
    public void box()
    {
        System.out.println("Boxing " + name);
    }

    public String toString()
    {
        // 显示披萨名称和配料
        StringBuffer display = new StringBuffer();
        display.append("---- " + name + " ----\n");
        display.append(dough + "\n");
        display.append(sauce + "\n");
        for (String topping : toppings)
        {
            display.append(topping + "\n");
        }
        return display.toString();
    }
}

// ------------------------------------------------------------------------

// 蛤蜊披萨
public class ClamPizza extends Pizza
{
    public ClamPizza()
    {
        name = "Clam Pizza";
        dough = "Thin crust";
        sauce = "White garlic sauce";
        toppings.add("Clams");
        toppings.add("Grated parmesan cheese");
    }
}

<br />


<br />

披萨店

public class PizzaStore
{
    SimplePizzaFactory factory; // 披萨店接收一个披萨制造工厂

    public PizzaStore(SimplePizzaFactory factory)
    {
        this.factory = factory;
    }

    // 客户可以订披萨
    public Pizza orderPizza(String type)
    {
        Pizza pizza;

        pizza = factory.createPizza(type); // 交给工厂来创建披萨

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }
}

<br />


<br />

披萨工厂

public class SimplePizzaFactory
{

    public Pizza createPizza(String type)
    {
        Pizza pizza = null;

        if (type.equals("cheese"))
        {
            pizza = new CheesePizza();
        } else if (type.equals("pepperoni"))
        {
            pizza = new PepperoniPizza();
        } else if (type.equals("clam"))
        {
            pizza = new ClamPizza();
        } else if (type.equals("veggie"))
        {
            pizza = new VeggiePizza();
        }
        return pizza;
    }
}

<br />


<br />

测试

public static void main(String[] args)
{
    // 创建个工厂
    SimplePizzaFactory factory = new SimplePizzaFactory();
    // 创建个披萨店
    PizzaStore store = new PizzaStore(factory);

    // 预订披萨,披萨店使用工厂创建披萨,然后披萨店自己处理披萨的烘烤、切片、装盒
    Pizza pizza = store.orderPizza("cheese");
    System.out.println("We ordered a " + pizza.getName() + "\n");
    System.out.println(pizza);

    pizza = store.orderPizza("veggie");
    System.out.println("We ordered a " + pizza.getName() + "\n");
    System.out.println(pizza);
}

简单工厂的问题和好处

<br />


<br />

工厂方法,重做披萨店

由于很多加盟商,在不同的地区开店,因此需要配合当地的口味,所以需要定制披萨店

披萨店重做

public abstract class PizzaStore
{
    // 这个方法就像一个工厂,由子类决定如何制造披萨
    public abstract Pizza createPizza(String item);

    public Pizza orderPizza(String type)
    {
        // 创建披萨,由子类来决定,你要创建的是什么样的披萨
        Pizza pizza = createPizza(type);
        System.out.println("--- Making a " + pizza.getName() + " ---");
        // 加工,由于披萨的风味和制作方法各有不同,因此也交给子类来决定,从而达到解耦的目的
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

// 开店
public class ChicagoPizzaStore extends PizzaStore
{

    public Pizza createPizza(String item)
    {
        if (item.equals("cheese"))
        {
            return new ChicagoStyleCheesePizza();
        } else if (item.equals("veggie"))
        {
            return new ChicagoStyleVeggiePizza();
        } else if (item.equals("clam"))
        {
            return new ChicagoStyleClamPizza();
        } else if (item.equals("pepperoni"))
        {
            return new ChicagoStylePepperoniPizza();
        } else
            return null;
    }
}

披萨可以自己定义加工自己的方式

public class ChicagoStyleClamPizza extends Pizza
{
    public ChicagoStyleClamPizza()
    {
        name = "Chicago Style Clam Pizza";
        dough = "Extra Thick Crust Dough";
        sauce = "Plum Tomato Sauce";

        toppings.add("Shredded Mozzarella Cheese");
        toppings.add("Frozen Clams from Chesapeake Bay");
    }

    public void cut()
    {
        System.out.println("Cutting the pizza into square slices");
    }
}

工厂方法模式的定义

定义了一个创建对象的接口,由子类决定要创建的对象是哪一个,工厂方法让类实例化推迟到了子类中。

设计原则 6 :依赖倒置原则

要依赖抽象,不要依赖具体类。

不能让高层组件依赖于具体的低层组件,在这个例子中,披萨店就是高层,披萨就是低层,而不管对于高层还是低层,都应该依赖于抽象,而不要依赖于具体的抽象类。

比如上面的PizzaStore依赖的就是Pizza这个抽象,而不是依赖于具体的某个Pizza子类

如何应用此原则

<br />


<br />

抽象工厂

现在不仅披萨店要定制,制作披萨的原料也要定制,因此需要不同的原料工厂

原料工厂

// 原料工厂,每种原料都对应一种创建的方法,抽象化,交给子类决定使用什么原料
public interface PizzaIngredientFactory
{
    public Dough createDough();

    public Sauce createSauce();

    public Cheese createCheese();

    public Veggies[] createVeggies();

    public Pepperoni createPepperoni();

    public Clams createClam();
}


// 芝加哥原料工厂,指定要使用哪些原料
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory
{
    public Dough createDough()
    {
        return new ThickCrustDough();
    }

    public Sauce createSauce()
    {
        return new PlumTomatoSauce();
    }

    public Cheese createCheese()
    {
        return new MozzarellaCheese();
    }

    public Veggies[] createVeggies()
    {
        Veggies veggies[] =
        { new BlackOlives(), new Spinach(), new Eggplant() };
        return veggies;
    }

    public Pepperoni createPepperoni()
    {
        return new SlicedPepperoni();
    }

    public Clams createClam()
    {
        return new FrozenClams();
    }
}

原料接口,同一种原料的生产之类的可能每个地区都不一样

public interface Cheese
{
    public String toString();
}

public class MozzarellaCheese implements Cheese
{
    public String toString()
    {
        return "Shredded Mozzarella";
    }
}

// 省略其他原料定义

披萨

public abstract class Pizza
{
    public String name;

    public Dough dough;
    public Sauce sauce;
    public Veggies veggies[];
    public Cheese cheese;
    public Pepperoni pepperoni;
    public Clams clam;

    public abstract void prepare();

    public void bake()
    {
        System.out.println("Bake for 25 minutes at 350");
    }

    public void cut()
    {
        System.out.println("Cutting the pizza into diagonal slices");
    }

    public void box()
    {
        System.out.println("Place pizza in official PizzaStore box");
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }

    public String toString()
    {
        StringBuffer result = new StringBuffer();
        result.append("---- " + name + " ----\n");
        if (dough != null)
        {
            result.append(dough);
            result.append("\n");
        }
        if (sauce != null)
        {
            result.append(sauce);
            result.append("\n");
        }
        if (cheese != null)
        {
            result.append(cheese);
            result.append("\n");
        }
        if (veggies != null)
        {
            for (int i = 0; i < veggies.length; i++)
            {
                result.append(veggies[i]);
                if (i < veggies.length - 1)
                {
                    result.append(", ");
                }
            }
            result.append("\n");
        }
        if (clam != null)
        {
            result.append(clam);
            result.append("\n");
        }
        if (pepperoni != null)
        {
            result.append(pepperoni);
            result.append("\n");
        }
        return result.toString();
    }
}


public class CheesePizza extends Pizza
{
    PizzaIngredientFactory ingredientFactory;

    // 由商店决定要用哪个工厂的原料
    public CheesePizza(PizzaIngredientFactory ingredientFactory)
    {
        this.ingredientFactory = ingredientFactory;
    }

    public void prepare()
    {
        System.out.println("Preparing " + name);
        // 只要是工厂就可以,不在乎具体是谁
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }
}

披萨店

父类不需要更改了,由子类自己决定自己的店需要的原料工厂

public class ChicagoPizzaStore extends PizzaStore
{

    protected Pizza createPizza(String item)
    {
        Pizza pizza = null;
        // 指定工厂
        PizzaIngredientFactory ingredientFactory = new ChicagoPizzaIngredientFactory();

        if (item.equals("cheese"))
        {
            pizza = new CheesePizza(ingredientFactory);
            pizza.setName("Chicago Style Cheese Pizza");

        } else if (item.equals("veggie"))
        {
            pizza = new VeggiePizza(ingredientFactory);
            pizza.setName("Chicago Style Veggie Pizza");

        } else if (item.equals("clam"))
        {
            pizza = new ClamPizza(ingredientFactory);
            pizza.setName("Chicago Style Clam Pizza");

        } else if (item.equals("pepperoni"))
        {
            pizza = new PepperoniPizza(ingredientFactory);
            pizza.setName("Chicago Style Pepperoni Pizza");

        }
        return pizza;
    }
}

抽象工厂的定义

提供一个接口,用于创建相关的,或者依赖的家族,而不需要明确指定具体类

工厂方法和抽象工厂的比较

上一篇 下一篇

猜你喜欢

热点阅读