设计模式-工厂模式

一、概述#

回顾:MySQL存储引擎如何建立个人博客

个人博客:后台建站,适合java程序员

什么是工厂模式?#

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

为什么要学习工厂模式?#

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

二、认识工厂模式#

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

假设我们有两种口味Pizza

Copy
/* * 抽象的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

Copy
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

Copy
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

Copy
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创建对象

Copy
// 创建一个纽约风味的芝士Pizza NyStyleCheesePizza nyPizza = new NyStyleCheesePizza();

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

简单工厂

Copy
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; } } }
Copy
// 创建简单工厂对象 SimplePizzaFactory pizzaFactory = new SimplePizzaFactory(); // 创建Pizza对象 NyStyleChieesePizza myPizza = pizzaFactory.createPizza("NYStyleChieesePizza");

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

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

工厂方法模式

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

Copy
// 抽象的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); }
Copy
// 纽约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; } } }

通过工厂方法创建对象

Copy
PizzaFactory pizzaFactory = new NYPizzaFactory(); // 创建一个蔬菜披萨 Pizza pizza = pizzaFactory.createPizza("NyStyleVeggiePizza");

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

抽象工厂模式

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

抽象原料工厂

Copy
// 为了简化, 这里的原料用字符串表示,其实每个原料应该用一个类表示 public interface PizzaIngredientFactory { public String createDough(); public String createSauce(); public String createChieese(); public String[] createVeggies(); public String createPepperoni(); }

芝士pizza原料工厂

Copy
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工厂

Copy
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; } }
Copy
// 具体的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

Copy
// 创建一个Pizza工厂 PizzaFactory pizzaFactory = new ChinaPizzaFactory(); Pizza clamPizza = pizzaFactory.createPizza("clam");

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

三、对比与分析#

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

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

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

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

如何选择?

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

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

posted @   Java填坑笔记  阅读(831)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示
CONTENTS