静态工厂模式&工厂模式&抽象工厂模式&解决的问题

本文通过披萨店的例子,详细介绍了工厂模式、简单工厂模式、工厂方法模式及抽象工厂模式的概念及其应用,展示了如何通过这些模式来封装变化,实现解耦。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提前总结:工厂模式的主要作用是封装变化,把经常变化的地方封装成一个类。这样可以避免重复,方便维护。使客户代码和实现代码解耦,客户在实例化对象时,依赖于接口,而不是具体的实现类。

问题的引出:假如你有一家披萨店,你只会做一种披萨

public class PizzaStore{
    public Pizza orderPizza(){
        Pizza pizza = new Pizza();
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}
后来你学会做多种披萨可供选择,修改orderPizza()

Pizza orderPizza(String type){
    Pizza pizza;
    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();
    }
}

但是这时候发现,每当学会一种披萨准备加进去的时候,都要修改orderPizza(),其实这是可以优化的,比如把主要发生变化的提出出来,单独的放在一个类中,这个方式又叫简单工厂:

一、简单工厂:可以创建原味披萨、蔬菜披萨等。比起都在PizzaSore中实现,简单工厂把披萨的创建封装起来,这样每次变化的时候就不用修改PizzaSore类了,而且还可以同时为多个PizzaStore提供服务。可以想象成把自己的披萨店分成两部分,一个是店面,一个是披萨加工工厂,而且这个工厂可以承接其他店面的订单。

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;
    }
}
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;
    }
}
店面生意很火爆,想开分店了怎么办,这时候要有一个统一的模式,所有的店和工厂共同遵守。把店面和工厂都抽象出来。每个店都有自己一系列的工厂。每个工厂只做一种披萨:

二、工厂模式

public abstract class PizzaStore{
    public Pizza orderPizza(String type){
        Pizza pizza = createPizza(type);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    abstract Pizza createPizza(type);
}

public class NYPizzaStore extends PizzaStore{
    Pizza createPizza(String item){
        if(item.equals("cheese")){
            return new NYStyleCheesePizza();
        }else if(item.equals("veggie")){
            return new NYStyleVeggiePizza();
        }else if(item.equals("clam")){
            return new NYStyleClamPizza();
        }else if(item.equals("pepperoni")){
            return new BYStylePepperoniPizza();
        }else return null;
}

public abstract class Pizza(){
    String name;
    String dough;
    String sauce;
    ArrayList toppings = new ArrayList();
    void prepare(){
        System.out.println("Preparing " + name);
        System.out.println("Tossing dough... " );
        System.out.println("Adding sause... " );
        System.out.println("Adding toppings: " );
        for(int i=0; i<topings.size();i++){
            System.out.pringtln("  " + toppings.get(i));
        }
        void bake(){
            System.out.println("Bake for 25 minutes at 350 " );
        }
        void cut(){
            System.out.println("Cutting the pizza into diagonal slicees " );
        }
        void box(){
            System.out.println("Place pizza in official PizzaStore box" );
        }
        public String getName(){
            return name;
        }
}

public class NYStyleCheesePizza extends Pizza{
    public NYStyleCheesePizza(){
        name = "NY Style Sauce and Cheese Pizza";
        dough = "Thin Crust Dough";
        sauce = "Marinara Sause";
        toppings.add("Grated Reggiano Cheese");
    }
}

public class ChicagoStyleCheesePizza extends Pizza{
    public ChicagoStyleCheesePizza(){
        name = "Chicago Style Deep Dish Cheese Pizza";
        dough = "Extra Thick Crust Dough";
        sauce = "Plum Tomato Sauce";
        toppings.add("Shredded Mozzarella Cheese");
    }
    void cut(){ //覆盖了cut()方法,将pizza切成正方形
        System.out.println("Cutting the pizza into square slices");
    }
}

public class PizzaTestDrive{
    public static void main(String[] args){
        PizzaStore nyStore = new NYPizzaStore();
        PizzaStore chicagoStore = new ChicagoPizzaStore();
        Pizza pizza = nyStore.orderPizza("cheese");
        System.out.println("Ethan ordered a " + pizza.getName() + "\n");
        pizza = chicagoStore.orderPizza("cheese");
        System.out.println("Joel ordered a " + pizza.getName() + "\n");
    }
}
总结工厂模式:这里的抽象店面和工厂只是起到行为规范的作用,大家都遵循相同的步骤做事。

设计模式有个很重要的设计原则:要依赖抽象,不要依赖具体,很明显,工厂模式的店面依赖于工厂的具体实现。观察工厂模式的工厂,每个店面都各自拥有一套自己的工厂,很浪费,完全可以整合成一个系列的工厂,这个系列的工厂需要一个管理部门,里面设小组对接原来的各个工厂。实际操作时,原来相对于每个店面的工厂就成了一个整理需求的部门,不做生产工作,而是直接把店面的需求传递给真正工厂的管理部门的小组。

三、抽象工厂

public interface PizzaIngredientFacory{  //工厂的管理部门
    public Dough createDough();
    public Sauce createSauce();
    public Cheese createSause();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();
}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory{  //对接纽约店面的小组,这里放着纽约店面的具体需求
    public Dough createDough(){
        return new ThinCrustDough();
    }
    public Sauce createSause(){
        return new MarinaraSause();
    }
    public Cheese createCheese(){
        return new ReggianoCheese();
    }
    public Veggies[] createVeggies(){
        Veggies veggies[] = {new Gralic(), new Onion(), new Mushroom()};
        return veggies;
    }
    public Pepperoni createPepperoni(){
        return new SlicedPepperoni();
    }
    public Clams createClam(){
        return new FreshClams();
    }
}

public abstract class Pizza{
    String name;
    Dough dough;
    Sauce sauce;
    Veggies veggies[];
    Cheese cheese;
    Pepperoni pepperonni;
    Clams clam;
    abstract void prepare();
    void bake(){
        System.out.println("Bake for 25 minutes at 350");
    }
    void cut(){
        System.out.println("Cutting the pizza into diagonal slices");
    }
    void box(){
        System.out.println("Place pizza in official PizzaStore box");
    }
    void setName(String name){
        this.name = name;
    }
    String getName(){
        return name;
    }
    public String toString(){}
}
public class CheesePizza extends Pizza{ //真正的生产工厂
    PizzaIngredientFactory ingredientFactory;
    public CheesePizza(PizzaIngredientFactory ingredientFactory){
        this.ingredientFactory = ingredientFactory;
    }
    void prepare(){
        System.out.println("Preparing " + name);
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }
}
public class NYPizzaStore extends PizzaStore{ //对接店面的工厂,用来调用真正生产工厂的管理部门
    pretected Pizza createPizza(String item){
        Pizza pizza = null;
        PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
        if (item.equals("cheese")){
            pizza = new CheesePizza(ingredientFactory);
            pizza.setName("New York Style Cheese Pizza");
        }else if (item.equals("veggie")){
            pizza = new VeggiePizza(ingredientFactory);
            pizza.setName("New York Style Veggie Pizza");
        }else if (item.equals("clam")){
            pizza = new ClamPizza(ingredientFactory);
            pizza.setName("New York Style Clam Pizza");
        }else if (item.equals("pepperoni")){
            pizza = new PepperoniPizza(ingredientFactory);
            pizza.setName("New York Style Pepperoni Pizza");
        }
        return pizza;
    }
}
虽然把工厂模式改变成抽象工厂模式,但是客户代码PizzaTestDrive并没有发生任何变化!变化是披萨的生产方式,原来由直接和店面对接的工厂生产,现在变成和店面对接的工厂调用实际的工厂生产,传入的参数是接口,然后由实际的工厂调用接口的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值