概述
工厂模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
实例
例举披萨店的例子,一个披萨店卖三种披萨,奶酪披萨、希腊披萨,胡椒披萨,他们分别继承自pizza类。
pizza类
public abstract class Pizza {
private String name;//名字
//准备原材料,不同的披萨不一样,因此,我们做成抽象方法
public abstract void prepare();
public void bake(){
System.out.println(name+"baking");
}
public void cut(){
System.out.println(name+"cutting");
}
//打包
public void box(){
System.out.println(name+"boxing");
}
public void setName(String name) {
this.name = name;
}
}
奶酪披萨类
继承自Pizza类实现其prepare() 方法,胡椒披萨、希腊披萨同理。
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println("为奶酪披萨准备材料");
setName("奶酪披萨");
}
}
工厂类方法
使用反射机制
public class Creator {
public static <T extends Pizza> T createProduct(Class<? extends Pizza> type){
Pizza t=null;
try {
t=(Pizza)Class.forName(type.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T)t;
}
}
方法的调用
public class Consumer {
public static void main(String[] args){
Creator.createProduct(PepperPizza.class).prepare();
}
}
上面使用反射机制虽好,但是调用者需要知道类名进行方法的调用,这样的操作有点多此一举。
改进
通过传入特定字符串对应工厂类生成的对象。
public class SimpleFactory {
//static 方法2
public static Pizza createPizza(String orderType){
Pizza pizza=null;
System.out.println("使用简单工厂模式");
if(orderType.equals("greek")){
pizza=new GreekPizza();
}else if(orderType.equals("cheese")){
pizza=new CheesePizza();
}else if(orderType.equals("pepper")){
pizza=new PepperPizza();
}
return pizza;
}
}
OrderPizza类
通过键盘写入字符串,调用工厂类传入该字符串
public class OrderPizza {
Pizza pizza=null;
public OrderPizza(){
setSimpleFactory();
}
public void setSimpleFactory(){
String orderType ="";
do{
orderType=gettype();
pizza=SimpleFactory.createPizza(orderType);
//输出pizza信息
if(pizza!=null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else{
System.out.println("订购失败");
break;
}
}while(true);
}
//可以获取客户系统希望订购的披萨种类
private String gettype(){
try{
BufferedReader strln=new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type:");
String str=strln.readLine();
return str;
}catch(IOException e){
e.printStackTrace();
return "";
}
}
}
调用类
*/ //相当于客户端发送,订单任务
public class PizzaStore {
public static void main(String[] args){
// new OrderPizza(); 原型
//使用简单工厂模式
new OrderPizza();
System.out.println("程序运行结束");
}
}
运行结果
输入greek,将会看到:
再次改进
利用枚举类型进行优化
public enum PizzaEnum {
CheesePizza(new CheesePizza(),"CheesePizza"),
PepperPizza(new PepperPizza(),"PepperPizza"),
GreekPizza(new GreekPizza(),"GreekPizza"),;
private Pizza pizza;
private String Name;
public String getName() {
return Name;
}
public static Pizza getPizzaByName(String name){
for (PizzaEnum c:PizzaEnum.values()) {
if(c.Name==name){
return c.pizza;
}
}
return null;
}
PizzaEnum(Pizza pizza, String name) {
this.pizza = pizza;
Name = name;
}
public void setName(String name) {
Name = name;
}
public Pizza getPizza() {
return pizza;
}
public void setPizza(Pizza pizza) {
this.pizza = pizza;
}
}
调用
public class PizzaEnumStore {
public static void getPizza(Pizza pizza) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
public static void main(String[] args) {
Pizza pizza = PizzaEnum.getPizzaByName("CheesePizza");
getPizza(pizza);
pizza = PizzaEnum.GreekPizza.getPizza();
getPizza(pizza);
}
}