设计模式学习--工厂模式(Factory Pattern)

来源:互联网 发布:深圳淘宝协会 编辑:程序博客网 时间:2024/06/06 01:57

设计模式学习--工厂模式(Factory Pattern)


2013年5月30日 设计模式学习记录

什么是工厂模式?

工厂模式可分为以下三种类型,需要根据不同需求来决定使用哪一种模式:
1. 简单工厂(不是真正意义上的设计模式)
2. 工厂方法(定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类实例化推迟到子类)
3. 抽象工厂(提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类)


面向对象原则:

多用组合,少用继承
针对接口编程,不针对实现编程
为交互对象之间的松耦合而努力
类应该对扩展开放,对修改关闭
依赖抽象,不是依赖具体类(新的原则)


要点:

1. 所有的工厂都是用来封装对象的创建。
2. 简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。
3. 工厂方法使用继承:把对象的创建委托给子类子类实现工厂方法来创建对象。
4. 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。
5. 所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。
6. 工厂方法允许类将实例化延迟到子类进行。
7. 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。
8. 依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象。
9. 工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。



工厂模式应用实例:比萨店



简单工厂实现

看看UML的类图


项目结构:



源代码:

/Pizza.java

package pizzas;import java.util.ArrayList;/*** *抽象pizza类 * @author wwj * */abstract public class Pizza {String name;String dough;String sauce;ArrayList toppings = new ArrayList();public String getName() {return name;}@Overridepublic 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;/** * 2013/5/25 * @author wwj * */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;/** * 2013/5/25 * @author wwj * */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;/** * 2013/5/25 * @author wwj * */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 * @author wwj * */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;/** * 2013/5/27 * @author wwj * 简单工厂方法 */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;/** * 2013/5/25 * @author wwj * 简单工厂的测试类 */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;/** * 2013/5/25 * @author wwj * */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;/** * 纽约披萨 * @author wwj * */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;/** * 芝加哥披萨 * @author wwj * */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;/** * 2013/5/25 * @author wwj * 让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 {@OverridePizza 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 {@OverridePizza 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;/** * 2013/5/25 * @author wwj * 工厂模式测试驱动类 */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;}@Overridevoid 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;}@Overridevoid 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;/** * 建造原料工厂 * @author wwj * 在接口中,每个原料都有一个对应的方法创造该原料 */public interface PizzaIngredientFactory {public Dough createDough();public Sauce createSauce();public Cheese createCheese();public Veggies[] createVeggies();public Pepperoni createPepperoni();public Clams createClam();}

package pizzaaf;/** * 创建纽约原料工厂 * @author wwj * */public class NYPizzaIngredientFactory implements PizzaIngredientFactory {@Overridepublic Dough createDough() {return new ThinCrustDough();}@Overridepublic Sauce createSauce() {return new MarinaraSauce();}@Overridepublic Cheese createCheese() {return new ReggianoCheese();}@Overridepublic Veggies[] createVeggies() {Veggies veggies[] = {new Garlic(), new Onion(), new MushRoom(), new RedPepper()};return veggies;}@Overridepublic Clams createClam() {return new FreshClams();}@Overridepublic Pepperoni createPepperoni() {return new SlicePepproni();}}


package pizzaaf;/** * 芝加哥披萨原料工厂 * @author wwj * */public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {@Overridepublic Dough createDough() {return new ThickCrustDough();}@Overridepublic Sauce createSauce() {return new plumTomatoSauce();}@Overridepublic Cheese createCheese() {return new Mozzarella();}@Overridepublic Veggies[] createVeggies() {Veggies veggies[] = {new BlackOlives(), new Spinach(), new EggPlant()};return veggies;}@Overridepublic Clams createClam() {return new FrozenClams();}@Overridepublic Pepperoni createPepperoni() {return new SlicedPepperoni();}}


所有原料接口,一系列产品族

package pizzaaf;public interface Cheese {@Overridepublic String toString();}

package pizzaaf;public interface Clams {@Overridepublic String toString();}

package pizzaaf;public interface Dough {@Overridepublic String toString();}

package pizzaaf;public interface Sauce {@Overridepublic String toString();}

package pizzaaf;public interface Veggies {@Overridepublic String toString();}

package pizzaaf;public interface Pepperoni {@Overridepublic 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";}}



关于工厂模式已经介绍完,蛮多内容的是吧。
什么时候用工厂方法和抽象方法呢?
来听听它们的告白:
抽象工厂:我是抽象工厂,当你需要创建产品家族和想让制造的相关产品集合起来时,你可以使用我。
工厂方法:我是工厂方法,我可以把你的客户代码从实例化的具体类中解耦。或者如果你目前还不知道将来需要实例化哪些具体类时,也可以用我。我的使用方式简单,只要把握继承成子类,并实现我的工厂方法就行了。

原创粉丝点击