什么是工厂模式?
工厂模式可分为以下三种类型,需要根据不同需求来决定使用哪一种模式:
1. 简单工厂(不是真正意义上的设计模式)
2. 工厂方法(定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类实例化推迟到子类)
3. 抽象工厂(提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类)
面向对象原则:
多用组合,少用继承
针对接口编程,不针对实现编程
为交互对象之间的松耦合而努力(将创建和使用分离成不同的类)
类应该对扩展开放,对修改关闭
依赖抽象,不是依赖具体类(新的原则)
要点:
1. 所有的工厂都是用来封装对象的创建。
2. 简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。
3. 工厂方法使用继承:把对象的创建委托给子类子类实现工厂方法来创建对象。
4. 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。
5. 所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。
6. 工厂方法允许类将实例化延迟到子类进行。
7. 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。
8. 依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象。
9. 工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。
10.用静态方法创建简单工程,是为了不需要创建对象,但是也有缺点,不能通过继承来改变创建方法的行为(当然也可以在抽象类中把方法定义为final或者static来防止子类对方法进行改变,双刃剑)。
工厂模式应用实例:比萨店
简单工厂实现
看看UML的类图
项目结构:
源代码:
/Pizza.java
- package pizzas;
- import java.util.ArrayList;
- /***
- * 抽象pizza类
- *
- */
- abstract public class Pizza {
- String name;
- String dough;
- String sauce;
- ArrayList toppings = new ArrayList();
- public String getName() {
- return name;
- }
- @Override
- public String toString() {
- StringBuffer display = new StringBuffer();
- display.append("----" + name + "----\n");
- display.append(dough + "\n");
- display.append(sauce + "\n");
- for(int i = 0; i < toppings.size(); i++) {
- display.append((String)toppings.get(i) + "\n");
- }
- return display.toString();
- }
- //准备
- public void prepare() {
- System.out.println("Preparing " + name);
- }
- //烘烤
- public void bake() {
- System.out.println("Baking " + name);
- }
- //切片
- public void cut() {
- System.out.println("Cutting " + name);
- }
- //装箱
- public void box() {
- System.out.println("Boxing " + name);
- }
- }
- package pizzas;
- /**
- *
- */
- public class CheesePizza extends Pizza {
- @SuppressWarnings("unchecked")
- public CheesePizza() {
- name = "Cheese Pizza";
- dough = "Regular Crust";
- sauce = "Marinara Pizza Sauce";
- toppings.add("Fresh Mozzarella");
- toppings.add("Parmesan");
- }
- }
- package pizzas;
- /**
- *
- */
- public class ClamPizza extends Pizza {
- @SuppressWarnings("unchecked")
- public ClamPizza() {
- name = "Clam Pizza";
- dough = "Thin crust";
- sauce = "White garlic sauce";
- toppings.add("Clams");
- toppings.add("Grated parmesan cheese");
- }
- }
- package pizzas;
- /**
- *
- */
- public class PepperoniPizza extends Pizza {
- @SuppressWarnings("unchecked")
- public PepperoniPizza() {
- name = "Pepperoni Pizza";
- dough = "Crust";
- sauce = "Marinara sauce";
- toppings.add("Sliced Pepperoni");
- toppings.add("Sliced Onion");
- toppings.add("Grated parmesan cheese");
- }
- }
- package pizzas;
- /**
- * 素食pizza
- *
- */
- public class VegglePizza extends Pizza {
- @SuppressWarnings("unchecked")
- public VegglePizza(){
- name = "Veggie Pizza";
- dough = "Crust";
- sauce = "Marinara sauce";
- toppings.add("Shredded mozzarella");
- toppings.add("Grated parmesan");
- toppings.add("Diced onion");
- toppings.add("Sliced mushrooms");
- toppings.add("Sliced red pepper");
- toppings.add("Sliced black olives");
- }
- }
/SimplePizzaFactory.java
- package pizzas;
- /**
- * 简单工厂方法
- */
- 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 VegglePizza();
- }
- return pizza;
- }
- }
/PizzaStore
- package pizzas;
- 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;
- }
- }
/PizzaTestDriver
- package pizzas;
- /**
- * 简单工厂的测试类
- */
- public class PizzaTestDriver {
- 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");
- pizza = store.orderPizza("veggie");
- System.out.println("We ordered a " + pizza.getName() + "\n");
- }
- }
工厂方法模式实现
项目结构:
/Pizza.java
把Pizza声明为抽象的,让所有具体比萨都必须派生自这个类。
- package pizzafm;
- import java.util.ArrayList;
- /**
- *
- */
- public abstract class Pizza {
- String name; //名称
- String dough; //面团类型
- String sauce; //一套佐料
- ArrayList toppings = new ArrayList();
- public void prepare() {
- System.out.println("Preparing " + name);
- System.out.println("Tossing dough...");
- System.out.println("Adding sauce...");
- System.out.println("Adding toppings: ");
- for(int i = 0; i < toppings.size(); i++) {
- System.out.println(" " + toppings.get(i));
- }
- }
- 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 String getName() {
- return name;
- }
- }
- package pizzafm;
- /**
- * 纽约披萨
- *
- */
- public class NYStyleCheesePizza extends Pizza {
- public NYStyleCheesePizza() {
- name = "NY Style Sauce and Cheese Pizza";
- dough = "Thin Crust Dough";
- sauce = "Marinara Sauce";
- toppings.add("Grated Reggiano Cheese");
- }
- }
- package pizzafm;
- public class NYStyleClamPizza extends Pizza {
- public NYStyleClamPizza() {
- name = "NY Style Clam Pizza";
- dough = "Thin Crust Dough";
- sauce = "Marinara Sauce";
- toppings.add("Grated Reggiano Cheese");
- toppings.add("Fresh Clams from Long Island Sound");
- }
- }
- package pizzafm;
- public class NYStylePepperoniPizza extends Pizza {
- public NYStylePepperoniPizza() {
- name = "NY Style Pepperoni Pizza";
- dough = "Thin Crust Dough";
- sauce = "Marinara Sauce";
- toppings.add("Grated Reggiano Cheese");
- toppings.add("Sliced Pepperoni");
- toppings.add("Garlic");
- toppings.add("Onion");
- toppings.add("Mushrooms");
- toppings.add("Red Pepper");
- }
- }
- package pizzafm;
- public class NYStyleVeggiePizza extends Pizza {
- public NYStyleVeggiePizza() {
- name = "NY Style Veggie Pizza";
- dough = "Thin Crust Dough";
- sauce = "Marinara Sauce";
- toppings.add("Grated Reggiano Cheese");
- toppings.add("Garlic");
- toppings.add("Onion");
- toppings.add("Mushrooms");
- toppings.add("Red Pepper");
- }
- }
- package pizzafm;
- /**
- * 芝加哥披萨
- *
- */
- 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");
- }
- public void cut() {
- System.out.println("Cutting the pizza into square slices");
- }
- }
- package pizzafm;
- 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");
- }
- }
- package pizzafm;
- public class ChicagoStylePepperoniPizza extends Pizza {
- public ChicagoStylePepperoniPizza() {
- name = "Chicago Style Pepperoni Pizza";
- dough = "Extra Thick Crust Dough";
- sauce = "Plum Tomato Sauce";
- toppings.add("Shredded Mozzarella Cheese");
- toppings.add("Black Olives");
- toppings.add("Spinach");
- toppings.add("Eggplant");
- toppings.add("Sliced Pepperoni");
- }
- public void cut() {
- System.out.println("Cutting the pizza into square slices");
- }
- }
- package pizzafm;
- public class ChicagoStyleVeggiePizza extends Pizza {
- public ChicagoStyleVeggiePizza() {
- name = "Chicago Deep Dish Veggie Pizza";
- dough = "Extra Thick Crust Dough";
- sauce = "Plum Tomato Sauce";
- toppings.add("Shredded Mozzarella Cheese");
- toppings.add("Black Olives");
- toppings.add("Spinach");
- toppings.add("Eggplant");
- }
- public void cut() {
- System.out.println("Cutting the pizza into square slices");
- }
- }
/PizzaStore.java
此类也是声明为抽象的,实例化比萨的责任由具体的子类来实现
- package pizzafm;
- /**
- * 让PizzaStore作为超类,让每个域类型都继承这个PizzaStore,每个子类各自决定如何制造披萨
- */
- public abstract class PizzaStore {
- public Pizza orderPizza(String type) {
- Pizza pizza;
- pizza = createPizza(type);
- pizza.prepare();
- pizza.bake();
- pizza.cut();
- pizza.box();
- return pizza;
- }
- abstract Pizza createPizza(String type);
- }
- package pizzafm;
- public class NYPizzaStore extends PizzaStore {
- @Override
- Pizza createPizza(String type) {
- if(type.equals("cheese")){
- return new NYStyleCheesePizza();
- } else if(type.equals("veggie")) {
- return new NYStyleVeggiePizza();
- } else if(type.equals("clam")) {
- return new NYStyleClamPizza();
- } else if(type.equals("pepperoni")){
- return new NYStylePepperoniPizza();
- } else return null;
- }
- }
- package pizzafm;
- public class ChicagoPizzaStore extends PizzaStore {
- @Override
- Pizza createPizza(String type) {
- if(type.equals("cheese")) {
- return new ChicagoStyleCheesePizza();
- } else if(type.equals("veggie")) {
- return new ChicagoStyleVeggiePizza();
- } else if(type.equals("clam")) {
- return new ChicagoStyleClamPizza();
- } else return null;
- }
- }
/PizzaTestDriver.java
- package pizzafm;
- /**
- * 工厂模式测试驱动类
- */
- public class PizzaTestDriver {
- 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");
- }
- }
抽象工厂模式实现
/Pizza.java
- package pizzaaf;
- public abstract class Pizza {
- String name;
- Dough dough;
- Sauce sauce;
- Veggies veggies[];
- Cheese cheese;
- Pepperoni pepperoni;
- 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() {
- 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();
- }
- }
- package pizzaaf;
- public class CheesePizza extends Pizza {
- PizzaIngredientFactory ingredientFactory;
- public CheesePizza(PizzaIngredientFactory ingredientFactory) {
- this.ingredientFactory = ingredientFactory;
- }
- @Override
- void prepare() {
- System.out.println("Preparing " + name);
- dough = ingredientFactory.createDough();
- sauce = ingredientFactory.createSauce();
- cheese = ingredientFactory.createCheese();
- }
- }
- package pizzaaf;
- public class ClamPizza extends Pizza {
- PizzaIngredientFactory ingredientFactory;
- public ClamPizza(PizzaIngredientFactory ingredientFactory) {
- this.ingredientFactory = ingredientFactory;
- }
- @Override
- void prepare() {
- System.out.println("PreParing " + name);
- dough = ingredientFactory.createDough();
- sauce = ingredientFactory.createSauce();
- cheese = ingredientFactory.createCheese();
- clam = ingredientFactory.createClam();
- }
- }
- package pizzaaf;
- public class PepperoniPizza extends Pizza {
- PizzaIngredientFactory ingredientFactory;
- public PepperoniPizza(PizzaIngredientFactory ingredientFactory) {
- this.ingredientFactory = ingredientFactory;
- }
- void prepare() {
- System.out.println("Preparing " + name);
- dough = ingredientFactory.createDough();
- sauce = ingredientFactory.createSauce();
- cheese = ingredientFactory.createCheese();
- veggies = ingredientFactory.createVeggies();
- pepperoni = ingredientFactory.createPepperoni();
- }
- }
- package pizzaaf;
- public class VeggiePizza extends Pizza {
- PizzaIngredientFactory ingredientFactory;
- public VeggiePizza(PizzaIngredientFactory ingredientFactory) {
- this.ingredientFactory = ingredientFactory;
- }
- void prepare() {
- System.out.println("Preparing " + name);
- dough = ingredientFactory.createDough();
- sauce = ingredientFactory.createSauce();
- cheese = ingredientFactory.createCheese();
- veggies = ingredientFactory.createVeggies();
- }
- }
/PizzaIngredientFactory.java
- package pizzaaf;
- /**
- * 建造原料工厂
- * 在接口中,每个原料都有一个对应的方法创造该原料
- */
- public interface PizzaIngredientFactory {
- public Dough createDough();
- public Sauce createSauce();
- public Cheese createCheese();
- public Veggies[] createVeggies();
- public Pepperoni createPepperoni();
- public Clams createClam();
- }
- package pizzaaf;
- /**
- * 创建纽约原料工厂
- *
- */
- public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
- @Override
- public Dough createDough() {
- return new ThinCrustDough();
- }
- @Override
- public Sauce createSauce() {
- return new MarinaraSauce();
- }
- @Override
- public Cheese createCheese() {
- return new ReggianoCheese();
- }
- @Override
- public Veggies[] createVeggies() {
- Veggies veggies[] = {new Garlic(), new Onion(), new MushRoom(), new RedPepper()};
- return veggies;
- }
- @Override
- public Clams createClam() {
- return new FreshClams();
- }
- @Override
- public Pepperoni createPepperoni() {
- return new SlicePepproni();
- }
- }
- package pizzaaf;
- /**
- * 芝加哥披萨原料工厂
- *
- */
- public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
- @Override
- public Dough createDough() {
- return new ThickCrustDough();
- }
- @Override
- public Sauce createSauce() {
- return new plumTomatoSauce();
- }
- @Override
- public Cheese createCheese() {
- return new Mozzarella();
- }
- @Override
- public Veggies[] createVeggies() {
- Veggies veggies[] = {new BlackOlives(), new Spinach(), new EggPlant()};
- return veggies;
- }
- @Override
- public Clams createClam() {
- return new FrozenClams();
- }
- @Override
- public Pepperoni createPepperoni() {
- return new SlicedPepperoni();
- }
- }
所有原料接口,一系列产品族
- package pizzaaf;
- public interface Cheese {
- @Override
- public String toString();
- }
- package pizzaaf;
- public interface Clams {
- @Override
- public String toString();
- }
- package pizzaaf;
- public interface Dough {
- @Override
- public String toString();
- }
- package pizzaaf;
- public interface Sauce {
- @Override
- public String toString();
- }
- package pizzaaf;
- public interface Veggies {
- @Override
- public String toString();
- }
- package pizzaaf;
- public interface Pepperoni {
- @Override
- public String toString();
- }
实现Cheese的类
- package pizzaaf;
- public class Mozzarella implements Cheese {
- public String toString() {
- return "Shredded Mozzarella";
- }
- }
- package pizzaaf;
- public class ReggianoCheese implements Cheese {
- public String toString() {
- return "Reggiano Cheese";
- }
- }
实现Clams的类
- package pizzaaf;
- public class FreshClams implements Clams {
- public String toString() {
- return "Fresh Clams from Long Island Sound";
- }
- }
- package pizzaaf;
- public class FrozenClams implements Clams {
- public String toString() {
- return "Frozen Clams from Chesapeake Bay";
- }
- }
实现Sauce的类
- package pizzaaf;
- public class MarinaraSauce implements Sauce {
- public String toString() {
- return "Marinara Sauce";
- }
- }
- package pizzaaf;
- public class plumTomatoSauce implements Sauce {
- public String toString() {
- return "Tomato sauce with plum tomatoes";
- }
- }
实现Veggies的类
- package pizzaaf;
- public class EggPlant implements Veggies {
- public String toString() {
- return "Eggplant";
- }
- }
- package pizzaaf;
- public class Onion implements Veggies {
- public String toString() {
- return "Onion";
- }
- }
- package pizzaaf;
- public class Spinach implements Veggies {
- public String toString() {
- return "Spinach";
- }
- }
- package pizzaaf;
- public class MushRoom implements Veggies {
- public String toString() {
- return "Mushrooms";
- }
- }
实现Pepperoni的类
实现Dough的类
- package pizzaaf;
- public class ThickCrustDough implements Dough {
- public String toString() {
- return "ThickCrust style extra thick crust dough";
- }
- }
- package pizzaaf;
- public class ThinCrustDough implements Dough {
- public String toString() {
- return "Thin Crust Dough";
- }
- }
关于工厂模式已经介绍完,蛮多内容的是吧。
什么时候用工厂方法和抽象方法呢?
来听听它们的告白:
抽象工厂:我是抽象工厂,当你需要创建产品家族和想让制造的相关产品集合起来时,你可以使用我。
工厂方法:我是工厂方法,我可以把你的客户代码从实例化的具体类中解耦。或者如果你目前还不知道将来需要实例化哪些具体类时,也可以用我。我的使用方式简单,只要把握继承成子类,并实现我的工厂方法就行了。