设计模式—工厂模式

转载注明出处 https://blog.csdn.net/qq_39071530/article/details/84890362

github地址 https://github.com/esmusssein777/designpatterns

设计模式目录 https://blog.csdn.net/qq_39071530/article/details/84849070

 

OO真正的精华,工厂模式。

在实例化的时候除了使用过new操作符之外,还可以使用工厂模式制造对象。当然在工厂模式里面代码是一样的,并不会少。

那么什么时候用到呢?

当实例化不希望他公开的进行时。还有不希望初始化的时候造成耦合问题的时候。

说了这么些,还不如写点代码。。。。

这里就直接用书上的代码好了。

假设你有一个Pizza店,并且你有很多种类型的Pizza,那么你会这样写代码:

Pizza orderPizza(String type){
		Pizza pizza;
		
		if(type.equals("chesse")){
			pizza = new CheesePizza();
		}else if(type.equals("greek")){
			pizza = new GreekPizza();
		}else if(type.equals("pepperoni")){
			pizza = new PepperoniPizza();
		}

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

当你看到下面这样的代码时就要小心了

        if(type.equals("chesse")){
		pizza = new CheesePizza();
	}else if(type.equals("greek")){
		pizza = new GreekPizza();
	}else if(type.equals("pepperoni")){
		pizza = new PepperoniPizza();
	}

因为当你以后改变条件的时候需要在原有的代码上修改,或者需求的变化一改再改。

我们就需要用工厂来帮助我们制造对象。

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 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;
	}
}

这是简单工厂。其实并不算是一种设计模式。代码量并没有变化,只是把创建Pizza的代码包装进一个类后,当以后实现改变的话,只需要修改这个类即可。我们正需要做的就是把实例化的过程,从客户的代码中删除。

当你使用了很多的if-else的时候你就要考虑一下是否使用简单工厂。

 

工厂模式

用书上的例子,当很多的加盟店加入到披萨店时,就需要使用工厂模式。

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

最简单的理解就是,当下面的代码又有很多个的时候。

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;
	}

不同的子类对应的createPizza不同的时候我们就是要用到工厂模式。举例来说就是你开的麻辣烫店在不同的地方要有不同的口味。比如开在重庆就要辣,开在海南就要清淡。

所以不同的地方createPizza不一样。于是就把createPizza方法推迟到子类去进行。

但是简单工厂并不能继承。

于是我们将代码写成这样。

public abstract class PizzaStore {
 
    //这里定义一个工厂方法
    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;
    }
}

里面最重要的是记住这行代码

abstract Pizza createPizza(String item);

这将具体的创建推迟到了子类

public class ChicagoPizzaStore extends PizzaStore {

    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;
    }
}

不同的子类有不同的方法。

划重点!!

所有的工厂模式都用来封装对象的创建。工厂方法模式让子类来决定创建的对象是什么,来达到将对象创建的过程封装的目的。

首先是总的披萨店,里面有create和order两个方法。但是每个地方的create方法不一样。

于是我们将create转为abstract,由子类继承的时候实现具体的食物。

再将具体创建那个对象封装进去。

这个就是工厂模式。

你可以想象一下如果不用工厂模式需要多少个  if-else 来判断创建那个类。

模式都是为我们减轻负担的。

 

抽象工厂模式

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

 

具体的例子用书的,当加盟店的原料也需要工厂来生产时,不同地方的原料不一样。

于是用抽象工厂模式,我们先来定义一个接口,就是需要原料的接口

public interface PizzaIngredientFactory {
 
    public Dough createDough();
    public Sauce createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();
 
}

 我们纽约的原料工厂是这样的,继承上面的接口、

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
 
    public Dough createDough() {
        return new ThinCrustDough();
    }
 
    public Sauce createSauce() {
        return new MarinaraSauce();
    }
 
    public Cheese createCheese() {
        return new ReggianoCheese();
    }
 
    public Veggies[] createVeggies() {
        Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
        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;
    Pepperoni pepperoni;
    Cheese cheese;
    Clams clam;

    public abstract void prepare();

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

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

    void box() {
        System.out.println("Place the pizza into offical PizzaStore box");
    }

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

    String getName() {
        return name;
    }

    public String toString() {
        return name + ((dough != null)?" Dough:"+dough.getClass().getName():"")
                + ((sauce != null)?" Sauce:" + sauce.getClass().getName():"")
                + ((cheese != null)?" Cheese:" + cheese.getClass().getName():"")
                + ((clam != null)?" Clam:" + clam.getClass().getName():"");
    }

}

public abstract void prepare();我们将准备的方法设为抽象方法。

当我们需要准备一个纽约的披萨时 。

‘我们继承该类

public class CheesePizza extends Pizza {
    //这里组合了一个PizzaIngredientFactory对象的引用,用于提供不同的原料
    PizzaIngredientFactory ingredientFactory;
 
    /**
     * 通过传入一个PizzaIngredientFactory原料工厂,我们可以在制作Pizza的时候动态的产生所需要的原料
     * @param ingredientFactory
     */
    
    public CheesePizza(PizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }
 
    void prepare() {
        System.out.println("Preparing " + name);
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }
}

像dough = ingredientFactory.createDough()这样的代码完美的体现了针对接口编程。

我们完全不需要要关心我们的原料工厂是哪一种。只需要在实现的时候将他传进来即可。

public class NYPizzaStore extends PizzaStore {
 
    protected 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;
    }
}

这里简单的画一下

抽象工厂的每个方法实际上看起来都像是工厂方法。就像每一个createDough()和createSauce()。 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值