一、概述

什么是工厂模式?

工厂模式(Factory Pattern)是最常见的一种设计模式之一。它主要是提供一种创建对象的最佳方法!

为什么要学习工厂模式?

与通过new来创建对象不同,使用工厂模式创建对象不会对客户端暴露创建逻辑,并且是通过统一个共同的接口指向新创建的对象。同事工厂模式能将创建对象的代码集中在一个对象或者方法中,可以避免代码中的重复,并且更方便维护。面向接口编程,这样的代码更具有弹性,可以应对未来的扩展。

二、认识工厂模式

案例:假设你有一个Pizza店,每天要做出不同口味的Pizza。

假设我们有两种口味Pizza

/*

* 抽象的Pizza类,Pizza制作一般包括准备,烘烤,切块,包装。

*/

public abstract class Pizza{

// Pizza名称

protected String name;

// 面团类型

protected String dough;

// 酱料

protected String sauce;

// 芝士

protected String cheese;

// 蛤蜊

protected String clam;

// 佐料

protected List toppings = new ArrayList();

// 准备

public void prepare() {

System.out.print("准备食材,添加调料:");

for (int i = 0; i < toppings.size(); i++) {

System.out.print(toppings.get(i)+" ");

}

};

// 烘烤

public void bake() {

System.out.println("烘烤20分钟...");

};

// 切块

public void cut() {

System.out.println("切成x块...");

};

// 包装

public void box() {

System.out.println("包装...");

}

// setter 和 getter方法省略

}

芝加哥风味的芝士Pizza

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");

}

public void cut() {

System.out.println("Cut the pizza into square slices");

}

}

纽约风味的蔬菜Pizza

public class NyStyleVeggiePizza extends Pizza{

public NyStyleVeggiePizza() {

name = "NY style Sauce and Veggie Pizza";

dough = "Thin Crust Dough";

sauce = "Marinara Sauce";

toppings.add("Grated Reggiano Veggie");

}

}

纽约风味的芝士Pizza

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");

}

}

通过new创建对象

// 创建一个纽约风味的芝士Pizza

NyStyleCheesePizza nyPizza = new NyStyleCheesePizza();

当使用new得到一个对象时,确实得到了一个具体类,是针对具体类实现,而不是接口。代码绑定具体类会导致代码脆弱,更缺乏弹性。

简单工厂

public class SimplePizzaFactory {

public Pizza createPizza(String type) {

Pizza pizza = null;

if (type.equals("NyStyleCheesePizza")) {

return new NyStyleChieesePizza();

} else if(type.endsWith("ChicagoStyleCheesePizza")) {

return new ChicagoStyleCheesePizza();

}else {

return null;

}

}

}

// 创建简单工厂对象

SimplePizzaFactory pizzaFactory = new SimplePizzaFactory();

// 创建Pizza对象

NyStyleChieesePizza myPizza = pizzaFactory.createPizza("NYStyleChieesePizza");

简单工厂将对象的创建过程进行了封装,用户不需要知道具体的创建过程,只需要调用工厂类获取对象即可。

这种简单工厂的写法是通过if else来判断对象创建过程的。简单工厂只是把new对象的问题转移到另一个类中在实际使用过程中,违背了 开放-关闭原则,当然有些情况下可以通过反射调用来弥补这种不足。

工厂方法模式

定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

// 抽象的Pizza工厂

public abstract class PizzaFactory {

public Pizza getPizza(String type) {

Pizza pizza;

pizza = createPizza(type);

pizza.prepare();

pizza.bake();

pizza.cut();

pizza.box();

return pizza;

}

protected abstract Pizza createPizza(String pizza);

}

// 纽约Pizza工厂(芝加哥pizza工厂跟这个类似)

public class NYPizzaFactory extends PizzaFactory {

protected Pizza createPizza(String type) {

if (type.equals("NyStyleChieesePizza")) {

return new NyStyleCheesePizza();

} else if (type.equals("NyStyleVeggiePizza")) {

return new NyStyleVeggiePizza();

}else {

return null;

}

}

}

通过工厂方法创建对象

PizzaFactory pizzaFactory = new NYPizzaFactory();

// 创建一个蔬菜披萨

Pizza pizza = pizzaFactory.createPizza("NyStyleVeggiePizza");

当使用工厂方法创建对象时,是在编写具体工厂类时决定创建的对象时哪一个,选择使用哪个工厂类,自然就决定了十几创建的是哪个对象。尽管只有一个具体工厂,工厂方法还是非常有用的!因为它将对象从“实现”从“使用”中解耦,如果增加对象或者改变对象,工厂是不会受到影响的!

抽象工厂模式

定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象原料工厂

// 为了简化, 这里的原料用字符串表示,其实每个原料应该用一个类表示

public interface PizzaIngredientFactory {

public String createDough();

public String createSauce();

public String createChieese();

public String[] createVeggies();

public String createPepperoni();

}

芝士pizza原料工厂

public class CheesePizzaIngredientFactory implements PizzaIngredientFactory {

public String createDough() {

return "薄地壳比萨生面团";

}

public String createSauce() {

return "纽约专用蘸料";

}

public String createChieese() {

return "Reggiano干酪";

}

public String[] createVeggies() {

return new String[]{"洋葱","生菜","香菇"};

}

public String createPepperoni() {

return "意大利辣香肠";

}

}

创建pizza工厂

public class ChinaPizzaFactory extends PizzaFactory {

public Pizza createPizza(String type) {

Pizza pizza = null;

PizzaIngredientFactory ingredientFactory = new ChinaPizzaIngredientFactory();

if(type.equals("cheese")) {

pizza = new CheesePizza(ingredientFactory);

pizza.setName("中国芝士pizza");

}else if (type.equals("clam")) {

pizza = new ClamPizza(ingredientFactory);

pizza.setName("中国蛤蜊pizza");

}

return pizza;

}

}

// 具体的Pizza类

public class ClamPizza extends Pizza {

PizzaIngredientFactory ingredientFactory;

public ClamPizza(PizzaIngredientFactory pizzaIngredientFactory) {

this.ingredientFactory = pizzaIngredientFactory;

}

public void prepare() {

System.out.println("Preparinging" + name);

// 根据pizza本身的特点,从工厂中获取自己需要的原料

dough = ingredientFactory.createDough();

sauce = ingredientFactory.createSauce();

clam = ingredientFactory.creatClam();

}

}

创建一个中国蛤蜊pizza

// 创建一个Pizza工厂

PizzaFactory pizzaFactory = new ChinaPizzaFactory();

Pizza clamPizza = pizzaFactory.createPizza("clam");

抽象工厂模式将'对象' 与 ‘’组成对象或者对象依赖的类‘’解耦。

三、对比与分析

通过new来创建对象是面向具体类编程,扩展性差!

简单工厂把全部的事情都在一个地方处理完了,但是当有新增或者修改的对象类时,很难进行扩展,违反了开闭原则。简单工厂并不能算是工厂模式,而是一种编程习惯,或者是一种方法的封装,并不具备弹性。

工厂方法是创建一个框架,让子类决定如何实现。虽然可能导致类会变多,代码稍微复杂,但是这样做最大的好处是更具有弹性。

工厂模式的好处:将创建对象的代码集中在一个对象或者方法中,可以避免代码中重复的代码,并且方便以后的维护。依赖接口,而不是具体的类。

如何选择?

当需要将对象家族和具体的对象集合结合起来时,可以使用抽象工厂。

当需要将客户代码从需要实例化的具体类中解耦,或者目前还不中知道将来实例化哪些具体类时,可以使用工厂方法。

java 工厂模式的写法_设计模式-工厂模式相关推荐

  1. java 工厂模式的写法_设计模式-Java-简单工厂模式--BitmapFactory

    上一篇,我们说了下MonkeyLei:设计模式-Java-观察者模式-RxJava 其中还利用到了反射的知识,另外也附上了很多我觉得分析还可以的链接. 这里我们看看简单工厂这块.除了这个还有其他几个: ...

  2. 反模式设计_设计模式:模式或反模式,这就是问题

    反模式设计 我最近遇到了Wiki页面" Anti-pattern" ,其中包含详尽的反模式列表. 其中一些对我来说很明显. 他们中的一些让我想了一下,其他的让我想了更多. 然后,我 ...

  3. 策略模式和工厂模式的区别_设计模式之工厂模式-工厂方法模式

    设计模式之工厂模式-工厂方法模式 大家好,欢迎来到污污弹公司,今天司小司又接到了一个新活-披萨项目. 来源:凯哥Java(kaigejava) 需求: 披萨项目: 要方便披萨品种的扩展.要便于维护.要 ...

  4. java 工厂模式的写法_java简单工厂模式是什么

    展开全部 所谓简单工厂模式, 就是将容易变化的地方, 考虑用一个独立Class来进行创造实体(Object)的过32313133353236313431303231363533e4b893e5b19e ...

  5. 策略模式和工厂模式的区别_设计模式系列 — 策略模式

    点赞再看,养成习惯,公众号搜一搜[一角钱技术]关注更多原创技术文章. 本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章. 前言 23种设计模式速记 单例(si ...

  6. java工厂模式式代码_简单工厂模式及其简单Java案例代码实现

    说明:本文是<大话设计模式>的学习记录及结合网上相关信息编写,原书代码例子采用C#编写,本文采用Java稍加改写.若有不当,欢迎指正,共同进步.java 1.简单工厂模式概述:设计模式 简 ...

  7. 工厂模式三部曲之三_抽象工厂模式(附三部曲源码)

    抽象工厂模式是对工厂模式的进一步抽象,是工厂模式中最为抽象和最具一般性的一种形态,提供了创建一系列相关或者相互依赖对象的接口,而无需指定他们的类型. 如果你对工厂模式还有些迷惑的,可以回顾下工厂模式的 ...

  8. java 外观模式类图_Java 设计模式——外观模式

    概述 今天要说的外观模式是一个相对简单的设计模式,而且在日常的开发中,可能你也会时常使用它,只是你可能并未想过这是一个设计模式.本文会从一些实例着手,来对本文要说明的外观模式进行尽可能全面的讲解.希望 ...

  9. java命令模式返回值_JAVA 设计模式 命令模式

    目录 用途 命令模式 (Command) 将一个请求 封装为一个对象,从而使你可以用 不同的请求对客户进行 参数化: 对请求排队或请求日志,以及支持可撤销的操作. 命令模式是一种行为型模式. 结构 图 ...

最新文章

  1. 上班族漫画(转收藏)
  2. python学会了能做什么-学会Python后都能做什么?介绍五种Python的实用场景
  3. leetcode(2)495——提莫攻击(C++),运算符优先级(+=,?,+,-)
  4. 各个平台的mysql重启命令
  5. vue-router query,parmas,meta传参
  6. MySQL purge 线程
  7. VS工程切换cuda版本
  8. Tensorflow -mofan1
  9. linux为mysql用户授权,Linux环境 Mysql新建用户和数据库并授权
  10. python 学习笔记 (核心)
  11. android 名称解释
  12. 本科生、研究生查询框架
  13. iphone4屏幕各部分尺寸
  14. 软件测试理论知识基础详细解说—总结
  15. coco2017数据集百度网盘链接
  16. Laravel框架使用maatwebsite/excel导出自动换行
  17. php 获取array的长度_php中获取数组长度的方法
  18. 百度云 文字识别API在线调用测试
  19. JS高级程序设计读书笔记(第五章 引用变量)
  20. myBatis set parameters是提示无效列索引

热门文章

  1. Windows 2000本地路由表
  2. 截取最后一个下划线前面的字符
  3. python12个基本语法_12-25python基本语法
  4. spring依赖注入_Spring源码阅读:Spring依赖注入容器
  5. jquery实现对radio赋值
  6. java 动态代理 阿bin_Android WebView 的方法只能在 UI 线程中运行
  7. html类选择器使用在什么场景,CSS选择器
  8. 直接输出代码_php代码:实时输出缩小的图像
  9. mysql 存储引擎接口_MySQL 的基础一(连接池, SQL接口, 查询解析器, 查询优化器, 存储引擎接口, 执行器,)...
  10. WSDM 2022 | 点击率模型特征交叉方向的发展及CAN模型介绍