对比学习headfirst和大话设计模式里面的经典模型
headfirst上用的是生产披萨的例子来说明工厂模式,工厂模式适用于生产某个类下的不同子类对象,例如Pizza类下的cheesePizza和VeggiaePizza,本质上都是披萨,只是特点不同,对于根据参数而生产不同对象的形式就很适合用简单工厂模式,避免将这个选择判断的过程写在主程序里面,因为抽取后还可以在其他地方使用。if..else if..也可以用switch case来代替。
package headfirst.factory.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 VeggiePizza();
}
return pizza;
}
}
披萨类是一个抽象类,目的就是为了让各个子类去继承实现,所以设置为抽象,但是抽象类里面并没有抽象方法,只是单纯的不想被生成,只想被继承。这也就是为啥抽象类中没有抽象方法的一个典型例子。
package headfirst.factory.pizzas;
import java.util.ArrayList;
abstract public class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
public String getName() {
return name;
}
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);
}
public String toString() {
// code to display pizza name and ingredients
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();
}
}
披萨的子类实现如下,只用写一个构造方法,将一些成员变量初始化一下就行。
package headfirst.factory.pizzas;
public class ClamPizza extends Pizza {
public ClamPizza() {
name = "Clam Pizza";
dough = "Thin crust";
sauce = "White garlic sauce";
toppings.add("Clams");
toppings.add("Grated parmesan cheese");
}
}
这样主程序中只需要有一个工厂对象就可以了。在工厂对象中输入对应的字符串就可以生成对应不同品种的披萨,返回给抽象类披萨Pizza接收,多态可以解耦。以后再新增不同的披萨品种就可以不改动主程序,直接写好新品种pizza类,并修改一下工厂类,在里面多加一种判断情况就可以了
package headfirst.factory.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;
}
}
工厂模式适用于生产某个类下的不同子类对象,例如Pizza类下的cheesePizza和VeggiaePizza,本质上都是披萨,只是特点不同,对于根据参数而生产不同对象的形式就很适合用简单工厂模式,避免将这个选择判断的过程写在主程序里面,因为抽取后还可以在其他地方使用。if..else if..也可以用switch case来代替。工厂类的好处如下:
而大话设计模式里面用的是设计计算器的例子,里面也涉及到了运算符这个抽象类,他下面可以有加法,减法,乘法,除法四个子类,也是根据输入的参数来生产对应的运算符对象,也是类似的处理形式,区别在于,披萨那里是将工厂设为成员变量,构造方法里面初始化,而这里的工厂就是一个普通的变量形式处理就行了。
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个数A");
double numberA = scanner.nextDouble();
System.out.println("请输入第二个数B");
double numberB = scanner.nextDouble();
System.out.println("请输入要进行的运算");
scanner.nextLine();
String operator = scanner.nextLine();
//工厂类(静态)方法产生所需的运算符对象
Operation operation = OperationFactory.createOperation(operator);
operation.numberA = numberA;
operation.numberB = numberB;
System.out.println("运算结果为" + operation.result());
}
}
public abstract class Operation {
public double numberA;
public double numberB;
public abstract double result();
}
同样是抽象的运算符类,类似于抽象类Pizza,工厂类用switch的形式实现
public class OperationFactory {
public static Operation createOperation(String operator) {
Operation operation = null;
switch (operator) {
case "+":
operation = new OperationAdd();
break;
case "-":
operation = new OperationSub();
break;
case "*":
operation = new OperationMul();
break;
case "/":
operation = new OperationDiv();
break;
default:
throw new RuntimeException("unsupported operation");
}
return operation;
}
}
具体的运算符乘法,实现抽象类运算符
public class OperationMul extends Operation {
@Override
public double result() {
return numberA * numberB;
}
}