工厂模式
Factory Design Pattern 工厂模式
工厂模式分类:
-
简单工厂模式
-
工厂方法模式
-
抽象工厂模式
示例
披萨生产和销售的项目:
- 披萨的种类 GreekPizz、CheesePiz等
- 披萨的制作过程有 prepare、bake、cut、box
- 完成披萨店订购功能
传统模式
- 思路分析(类图)
//披萨抽象类
public abstract class Pizza{
//披萨名字
private String name;
public void setName(){
this.name=name;
}
public String getName(){
return this.name;
}
//准备方法
public abstract void prepare();
//烘培
public void bake(){
System.out.println(this.name+" baking");
}
//切割
public void cut(){
System.out.println(this.name+" cutting");
}
//打包
public void box(){
System.out.println(this.name+" boxing");
}
}
//奶酪披萨
public class CheesePizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
System.out.println(" 给制作奶酪披萨 准备原材料 ");
}
}
//希腊披萨
public class GreekPizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
System.out.println(" 给希腊披萨 准备原材料 ");
}
}
//中国披萨
public class CheesePizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
System.out.println(" 给制作奶酪披萨 准备原材料 ");
}
}
//披萨订单类
public class OrderPizza{
//披萨
Pizza pizza=null;
//披萨类型
String orderType;
/**
* 获取pizza种类
* 此处可以根据需求,定义如何获取披萨类型
* @return
*/
private String getOrderType() {
BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("--------------------------------------------------");
System.out.println("input pizza 种类:");
String orderType = null;
try {
orderType = strIn.readLine();
} catch (IOException e) {
e.printStackTrace();
return "";
}
return orderType;
}
public OrderPizza(){
do{
//获取披萨类型
orderType=getOrderType();
switch(orderType){
case "greek":
pizza=new GreekPizza();
pizza.setName(" 希腊披萨 ");
break;
case "cheese":
pizza = new CheesePizza();
pizza.setName(" 奶酪披萨 ");
break;
case "pepper":
pizza = new PepperPizza();
pizza.setName(" 胡椒披萨 ");
break;
default:
System.out.println("请输入正确的披萨名称");
pizza=null;
break;
}
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}while(true);
}
}
- 分析
- 优点是比较好理解,简单易操作。
- 缺点是违反了设计模式的ocp原则,即对扩展开放,对修改关闭。
- 如果新增一种披萨代码修改如下:
//1.新增pizza类
public class PepperPizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
System.out.println(" 给胡椒披萨准备原材料 ");
}
}
//2.在订单orderPizza的switch语句中增加新的判断
case "pepper":
pizza = new PepperPizza();
pizza.setName(" 胡椒披萨 ");
break;
- 改进思路
把创建Pizza对象封装到一个类中,这样我们有新的Pizza类型时,只需要修改该类就可,其他有创建到Pizza对象的代码就不需要修改了。
简单工厂模式
- 基本介绍
- 简单工厂模式是属于创建型模式,是工厂模式的一种,也叫静态工厂模式。
- 简单工厂模式是定义一个工厂对象的类,由这个类来封装实例化对象的行为代码。
- 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。
- 工厂模式的类图
//简单工厂类
public class SimpleFactory {
/**
* 简单工厂模式(静态工厂模式)
*
* @param orderType
* @return
*/
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new GreekPizza();
pizza.setName(" 希腊披萨 ");
} else if ("cheese".equals(orderType)) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披萨 ");
} else if ("pepper".equals(orderType)) {
pizza = new PepperPizza();
pizza.setName(" 胡椒披萨 ");
} else {
pizza = null;
}
return pizza;
}
}
//披萨订单类
public class OrderPizza {
/**
* 简单工厂
*/
SimpleFactory simpleFactory;
/**
* 披萨
*/
Pizza pizza = null;
public OrderPizza(SimpleFactory simpleFactory) {
setFactory(simpleFactory);
}
/**
* 获取pizza种类
*
* @return
*/
private String getOrderType() {
BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String orderType = null;
try {
orderType = strIn.readLine();
} catch (IOException e) {
e.printStackTrace();
return "";
}
return orderType;
}
public void setFactory(SimpleFactory simpleFactory) {
/**
* 披萨类型
*/
String orderType = "";
this.simpleFactory = simpleFactory;
do {
orderType = getOrderType();
pizza = this.simpleFactory.createPizza(orderType);
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购pizza失败");
}
} while (true);
}
}
- 分析
- 简单工厂模式解决了披萨对象在订单类中生成,简单工厂类负责创建具体的披萨对象。
- 在简单工厂类的创建方法中,使用了switch-case结构,违背开闭原则。
- 在考虑到可读性的前提下,如果能够保证不频繁的增删具体实现类,是可以使用此种设计方式的。
- 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
工厂方法模式
- 基本介绍
- 工厂方法模式定义了一个创建对象的抽象方法,由子类决定决定实例化的类。
- 工厂方法模式比着简单工厂模式更符合开闭原则。
- 工厂方法模式类图
//抽象披萨订单
public abstract class AbstractOrderPizza {
//定义一个抽象方法,createPizza , 让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
// 构造器
public AbstractOrderPizza() {
Pizza pizza = null;
String orderType; // 订购披萨的类型
do {
orderType = getType();
pizza = createPizza(orderType); //抽象方法,由工厂子类完成
//输出pizza 制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
}
//北京工厂
public class BJOrderPizzaFactory extends AbstractOrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
// TODO Auto-generated method stub
return pizza;
}
}
//伦敦工厂
public class LDPizzaFactory extends AbstractOrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new LDPepperPizza();
}
// TODO Auto-generated method stub
return pizza;
}
}
//披萨店使用
public class PizzaStore {
public static void main(String[] args) {
String loc = "bj";
if (loc.equals("bj")) {
//创建北京口味的各种Pizza
new BJPizzaOrderFactory();
} else {
//创建伦敦口味的各种Pizza
new LDOrderPizzaFactory();
}
}
}
- 分析
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现产品类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断转移到了客户端代码来进行。
抽象工厂模式
- 基本介绍
- 抽象工厂模式定义一个接口用于创建相关或有依赖关系的对象簇
- 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
- 从设计层面看抽象工厂模式就是对简单工厂模式的改进(或者进一步的抽象)
- 抽象工厂模式类图
//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
//让下面的工厂子类来 具体实现
public Pizza createPizza(String orderType);
}
//这是工厂子类
public class BJFactory implements AbsFactory {
@Override
public Pizza createPizza(String orderType) {
System.out.println("~使用的是抽象工厂模式~");
// TODO Auto-generated method stub
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
return pizza;
}
}
public class LDFactory implements AbsFactory {
@Override
public Pizza createPizza(String orderType) {
System.out.println("~使用的是抽象工厂模式~");
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
public class OrderPizza {
AbsFactory factory;
// 构造器
public OrderPizza(AbsFactory factory) {
setFactory(factory);
}
private void setFactory(AbsFactory factory) {
Pizza pizza = null;
String orderType = ""; // 用户输入
this.factory = factory;
do {
orderType = getType();
// factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
pizza = factory.createPizza(orderType);
if (pizza != null) { // 订购ok
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购失败");
break;
}
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
注:
- 三种设计模式对比者可以更好的理解,先从简单工厂模式开始,然后工厂方法模式,在看抽象工厂模式,了解演变过程。
- 上图中工厂方法模式和抽象工厂模式都是尚硅谷老师讲解的,极客学院讲解的不太一样,又对照着大话设计模式看了一遍,各有侧重点吧,重要看自己怎么理解啦。