定义:
- 简单工厂模式属于创建型模式,是工厂模式的一种,简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,简单工厂模式是工厂模式家族最简单实用的模式。
- 定义了一个创建对象的类,由这个类封装实例化对象的行为。
- 在软件开发中,当我们会用到大量的创建某种、某类、或者某批对象时,就会使用到工厂模式。
场景:一个关于pizza的项目。
4. pizza的种类很多,GreekPizza、CheesePizza等。
5. Pizza的制作流程:prepare、bake、cut、box。
6. 完成披萨店的订购功能。
第一版UML图及代码:
public abstract class Pizza {
protected String name;
public void setName(String name){
this.name = name;
}
/**
* 每种pizza准备的原材料都不一样,所以将该流程延迟到子类自己实现。
*/
public abstract void prepare();
//烘焙、切割、打包流程一样,就在父类实现了,将不变的部分与会变化的部分分开
public void bake(){
System.out.println(name + " 进行烘焙流程。");
}
public void cut(){
System.out.println(name + " 进行切割流程。");
}
public void box(){
System.out.println(name + " 进行包装流程。");
}
}
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println(name + " 在准备制作的原材料。");
}
}
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println(name + " 在准备制作的原材料。");
}
}
public class PizzaOrder {
public void addOrder(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Pizza pizza = null;
while (true){
try {
String name = reader.readLine();
if ("cheese".equalsIgnoreCase(name)){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}
else if ("greek".equalsIgnoreCase(name)){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}
else {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
PizzaOrder order = new PizzaOrder();
order.addOrder();
}
}
//第一版分析:
//1. 将制作披萨的流程实现在调用方PizzaOrder 中,假如新增一种SaladPizza,就要修改调用方PizzaOrder 的代码,如果有多个PizzaOrder ,就使得系统更加地复杂。这就违反了开闭原则。对修改进行开放了。
if ("cheese".equalsIgnoreCase(name)){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}
else if ("greek".equalsIgnoreCase(name)){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}
else if ("Salad".equalsIgnoreCase(name)){
pizza = new SaladPizza();
pizza.setName("沙拉披萨");
}
第二版(使用简单工厂模式)的UML及代码:
public abstract class Pizza {
protected String name;
public void setName(String name){
this.name = name;
}
/**
* 每种pizza准备的原材料都不一样,所以将该流程延迟到子类自己实现。
*/
public abstract void prepare();
//烘焙、切割、打包流程一样,就在父类实现了,将不变的部分与会变化的部分分开
public void bake(){
System.out.println(name + " 进行烘焙流程。");
}
public void cut(){
System.out.println(name + " 进行切割流程。");
}
public void box(){
System.out.println(name + " 进行包装流程。");
}
}
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println(name + " 在准备制作的原材料。");
}
}
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println(name + " 在准备制作的原材料。");
}
}
public class PizzaFactory {
public Pizza createPizza(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Pizza pizza = null;
while (true){
try {
String name = reader.readLine();
if ("cheese".equalsIgnoreCase(name)){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}
else if ("greek".equalsIgnoreCase(name)){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}
else {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return pizza;
}
}
public class PizzaOrder {
private PizzaFactory pizzaFactory = new PizzaFactory();
public void addOrder(){
Pizza pizza = pizzaFactory.createPizza();
}
public static void main(String[] args) {
PizzaOrder order = new PizzaOrder();
order.addOrder();
}
}
//分析:这个代码使用了简单工厂模式进行改进,将制作pizza的细节封装在了工厂中,
//调用方PizzaOrder 无需知道细节,只管调用PizzaFactory.createPizza()就可以获得想要的
//pizza。当新增一种pizza时,只需要修改工厂,无需修改调用方PizzaOrder ,符合开闭原则。
静态工厂是一种特殊的简单工厂,实现代码:
public class PizzaFactory {
public **static** Pizza createPizza(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Pizza pizza = null;
while (true){
try {
String name = reader.readLine();
if ("cheese".equalsIgnoreCase(name)){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}
else if ("greek".equalsIgnoreCase(name)){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}
else {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return pizza;
}
}
简单工厂模式适用于类比我是很多,并且不会经常增加新的类别,比如如果Pizza经常退出新品,或者品类很多,就不太适合使用简单工厂模式,因为每增加一种类别,就要修改工厂类的代码,违反了开闭原则。