1. 工厂设计模式
1.1 应用场景
由于需求的变化,一个类的子类经常面临着剧烈的变化,但他却拥有比较稳定的接口。使用一种封装机制来“隔离这种易变对象的变化”,工厂方法定义一个用于创建对象的接口,让子类来确定创建哪一个具体类的对象,将对象的实例化延迟。
1.2 概念
定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。
1.3 Class Diagram
在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。
下图中,Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,这个产品对象由 factoryMethod() 方法创建,也称为“工厂方法”。该方法是抽象的,需要由子类去实现。在抽象的Factory中,任何其他实现的方法,都可能使用到这个工厂方法所制造出来的产品,但只有子类真正实现了这个工厂方法并创建产品。
1.4 Implementation
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList<String> toppings = new ArrayList<String>();
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);
}
}
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 pizza in official PizzaStore box");
}
public String getName() {
return 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 abstract class PizzaStore {
public Pizza orderPizza(String type){
Pizza pizza;
pizza=createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public abstract Pizza createPizza(String type);
}
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");
}
}
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() {
System.out.println("Cutting the pizza into square slices");
}
}
public class ChicagoStylePizzaStore extends PizzaStore{
@Override
public Pizza createPizza(String type) {
if(type.equals("cheese"))
return new ChicagoStyleCheesePizza();
return null;
}
}
public class NYStylePizzaStore extends PizzaStore{
@Override
public Pizza createPizza(String type) {
if(type.equals("cheese"))
return new NYStyleCheesePizza();
return null;
}
}
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStylePizzaStore=new NYStylePizzaStore();
PizzaStore chicagoStylePizzaStore=new ChicagoStylePizzaStore();
Pizza nyStylePizza = nyStylePizzaStore.orderPizza("cheese");
System.out.println("Ethan ordered a " + nyStylePizza.getName() + "\n");
Pizza chicagoPizza = chicagoStylePizzaStore.orderPizza("cheese");
System.out.println("Ethan ordered a " + chicagoPizza.getName() + "\n");
}
}
1.5 JDK
- java.util.Calendar
- java.util.ResourceBundle
- java.text.NumberFormat
- java.nio.charset.Charset
- java.net.URLStreamHandlerFactory
- java.util.EnumSet
- javax.xml.bind.JAXBContext
2. 抽象工厂方法
2.1 应用场景
一系列相互依赖的对象有不同的具体实现。提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合。
2.2 概念
提供一个接口,用于创建 相关的对象家族,而不需要明确的指定具体类。抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或者关心实际产出的产品是什么。这样一来客户就从具体的产品中被解耦。
2.3 Class Diagram
抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。
抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 createProductA() 和 createProductB() 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂方法模式的定义。
至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。
从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。
2.4 Implementation
public interface Cheese {
public String toString();
}
public interface Clams {
public String toString();
}
public interface Dough {
public String toString();
}
public class FreshClams implements Clams {
public String toString() {
return "Fresh Clams from Long Island Sound";
}
}
public class Garlic implements Veggies {
public String toString() {
return "Garlic";
}
}
public class MarinaraSauce implements Sauce {
public String toString() {
return "Marinara Sauce";
}
}
public class Mushroom implements Veggies {
public String toString() {
return "Mushrooms";
}
}
public class Onion implements Veggies {
public String toString() {
return "Onion";
}
}
public interface Pepperoni {
public String toString();
}
public class RedPepper implements Veggies {
public String toString() {
return "Red Pepper";
}
}
public class ReggianoCheese implements Cheese {
public String toString() {
return "Reggiano Cheese";
}
}
public interface Sauce {
public String toString();
}
public class SlicedPepperoni implements Pepperoni {
public String toString() {
return "Sliced Pepperoni";
}
}
public class ThinCrustDough implements Dough {
public String toString() {
return "Thin Crust Dough";
}
}
public interface Veggies {
public String toString();
}
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClams();
}
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 ClamPizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public ClamPizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
public void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
clam = ingredientFactory.createClams();
}
}
public class PepperoniPizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public PepperoniPizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
public void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
veggies = ingredientFactory.createVeggies();
pepperoni = ingredientFactory.createPepperoni();
}
}
public class VeggiePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public VeggiePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
public void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
veggies = ingredientFactory.createVeggies();
}
}
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();
}
@Override
public Clams createClams() {
return new FreshClams();
}
}
public abstract class PizzaStore {
protected 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 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;
}
}
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
System.out.println("Ethan ordered a " + pizza + "\n");
pizza = nyStore.orderPizza("clam");
System.out.println("Ethan ordered a " + pizza + "\n");
pizza = nyStore.orderPizza("pepperoni");
System.out.println("Ethan ordered a " + pizza + "\n");
pizza = nyStore.orderPizza("veggie");
System.out.println("Ethan ordered a " + pizza + "\n");
}
}