ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

简单工厂、工厂方法、抽象工厂到底有什么区别?一文讲透工厂模式的演进

简单工厂、工厂方法、抽象工厂到底有什么区别?一文讲透工厂模式的演进 引言很多初学者分不清简单工厂、工厂方法、抽象工厂其实它们并不是三个孤立的设计模式而是同一条演进路线简单工厂 → 工厂方法 → 抽象工厂。简单工厂把创建逻辑抽离却堆满 if-else工厂方法把工厂也抽象掉新增产品不改老代码抽象工厂则解决一族产品的配套创建问题。每一步升级都是用更高复杂度换取更强扩展性。目录一. 简单工厂二. 工厂方法三. 抽象工厂实战软考真题一. 简单工厂1. 结构图2. 代码实现①创建抽象类、具体类abstract class Product{ public abstract void info(); } class ProductA extends Product{ Override public void info() { System.out.println(产品的信息A); } } class ProductB extends Product{ Override public void info() { System.out.println(产品的信息B); } }②创建工厂类class Factory{ public static Product createProduct(String type){ Product product null; switch (type){ case A: product new ProductA(); break; case B: product new ProductB(); break; default: System.out.println(没有 type 类型的产品); break; } return product; } }测试一下//简单工厂模式 public class SimpleFactory { public static void main(String[] args) { Product productA Factory.createProduct(A); productA.info(); Product productB Factory.createProduct(B); productB.info(); Product productC Factory.createProduct(C); productC.info(); } }运行结果如下3. 解读序号精髓点说明代码体现1返回类型是抽象类实际值是具体类编译期类型为父类型运行期类型为子类本质是多态向上转型public static Product createProduct(...)返回Product实际new ProductA()2父 子多态思想客户端只依赖抽象Product不依赖任何具体产品类Product productA Factory.createProduct(A);3封装创建客户端不再 newnew被关进工厂客户端与具体类解耦客户端只写Factory.createProduct(A)不出现new ProductA()4集中判断switch/if-else工厂内部集中决定创建哪个产品一目了然switch(type){ case A: ... case B: ... }5静态方法调用方便不用先创建工厂对象直接类名调用public static Product createProduct(...)6客户端只认“能干什么”不认“是谁”客户端只调抽象方法具体执行哪个由运行时对象决定productA.info();只调抽象方法7switch 是特征也是软肋新增产品要改 switch违反开闭原则这正是被工厂方法取代的原因每加一个产品就要加一个case8静态方法无法被继承重写简单直接但工厂无法扩展这是“简单”的代价static方法不能被 override4. 最大的缺点违反“开放—封闭”原则现在我们的工厂类只支持创建A、B两种产品但是后续加入产品C时遇到如下问题说白了此时我们由于新加了一个产品C导致不得不修改工厂类的代码。这的确违反了“开放—封闭”原则。因为我们通常对扩展是开放的对修改是关闭的。对应到此处就是你扩展了产品C是没问题的但是不能修改工厂类的代码。由于简单工厂模式存在上述缺陷因此引出下面的工厂方法模式.二. 工厂方法1. 结构图2. 代码实现①创建产品接口、实现类interface Product{ public void info(); } class ProductA implements Product{ Override public void info() { System.out.println(产品的信息A); } } class ProductB implements Product{ Override public void info() { System.out.println(产品的信息B); } }②创建工厂接口、实现类interface Factory{ public Product createProduct(); } class FactoryA implements Factory{ Override public Product createProduct() { return new ProductA(); } } class FactoryB implements Factory{ Override public Product createProduct() { return new ProductB(); } }测试一下//工厂方法 public class test { public static void main(String[] args) { Factory factoryA new FactoryA(); Product productA factoryA.createProduct(); productA.info(); Factory factoryB new FactoryB(); Product productB factoryB.createProduct(); productB.info(); } }运行效果3. 解读序号要点说明代码体现1工厂也抽象成接口工厂不再是一个具体类而是一个接口定义创建产品的规范interface Factory { Product createProduct(); }2每个产品配一个专属工厂一个具体产品对应一个具体工厂职责单一FactoryA→ProductAFactoryB→ProductB3返回类型是抽象产品实际值是具体产品和简单工厂一样编译期是父类型运行期是子类本质是多态public Product createProduct()返回Product实际new ProductA()4父 子多态思想客户端只依赖Product和Factory两个抽象不依赖具体类Product productA factoryA.createProduct();5客户端不再 switch 判断简单工厂的 switch 被“多态分发”取代选哪个工厂由客户端决定客户端选new FactoryA()还是new FactoryB()6新增产品不改老代码加一个产品 加一个产品类 加一个工厂类符合开闭原则新增ProductC只需加ProductCFactoryC7代价类数量翻倍每个产品都要配一个工厂类的数量成对增长N 个产品 → N 个产品类 N 个工厂类8只解决“一个产品等级”工厂接口里只有一个createProduct()搞不定产品族无法保证“按钮复选框”配套创建4. 优点遵循“开放—封闭”原则举例我们新加一个产品C只需要增加一个对应的专属工厂类即可而无需修改任何之前的代码也就是对拓展开放对修改关闭可见我们新增一个产品时只需要新增对应的类、具体工厂类即可而无需修改之前的任何代码这就遵守了“开放—封闭”原则即对新增开放对修改关闭。说白了就是当新增一部分功能时可以新增代码但尽量不要修改之前的代码。5. 补充这个结构图其实和上面的结构图是一个意思只不过画的方式有区别但表达的意思是一样的。下面的事项看看就行了解即可。三. 抽象工厂1. 结构图2. 代码实现// 抽象产品族 // 产品等级 1按钮 interface Button { void render(); } // 产品等级 2复选框 interface Checkbox { void render(); } // 具体产品Windows 家族 class WindowsButton implements Button { Override public void render() { System.out.println(渲染 Windows 按钮); } } class WindowsCheckbox implements Checkbox { Override public void render() { System.out.println(渲染 Windows 复选框); } } // 具体产品Mac 家族 class MacButton implements Button { Override public void render() { System.out.println(渲染 Mac 按钮); } } class MacCheckbox implements Checkbox { Override public void render() { System.out.println(渲染 Mac 复选框); } } // 抽象工厂定义一族产品的创建接口 interface GUIFactory { Button createButton(); Checkbox createCheckbox(); } // 具体工厂Windows 工厂 class WindowsFactory implements GUIFactory { Override public Button createButton() { return new WindowsButton(); } Override public Checkbox createCheckbox() { return new WindowsCheckbox(); } } // 具体工厂Mac 工厂 class MacFactory implements GUIFactory { Override public Button createButton() { return new MacButton(); } Override public Checkbox createCheckbox() { return new MacCheckbox(); } } // 客户端 public class AbstractFactoryTest { public static void main(String[] args) { // 只选一次工厂之后创建的所有组件都自动配套 GUIFactory factory new WindowsFactory(); // GUIFactory factory new MacFactory(); // 换一行就切换整个产品族 Button button factory.createButton(); Checkbox checkbox factory.createCheckbox(); button.render(); checkbox.render(); } }3. 解读序号优点说明代码体现1保证产品族内的一致性同一个工厂创建出的产品天然配套不会出现“Windows 按钮配 Mac 复选框”WindowsFactory只会产出WindowsButtonWindowsCheckbox2客户端与具体产品解耦客户端只依赖抽象Button、Checkbox、GUIFactory不碰任何具体类客户端代码里没有new WindowsButton()3切换产品族非常方便换一个工厂整个产品族一起换只改一行new WindowsFactory()→new MacFactory()4符合开闭原则对新增产品族而言新增一个产品族如 Linux 风格只需加一套产品类 一个工厂类不改老代码新增LinuxButton、LinuxCheckbox、LinuxFactory5职责清晰符合单一职责每个具体工厂只负责创建自己那一族产品MacFactory只造 Mac 系列6便于统一管理与扩展一族产品的创建逻辑集中在一个工厂里规范统一所有 Mac 组件的创建都归MacFactory4. 优点抽象工厂最大的优点保证一族产品配套一致且切换产品族只需换一个工厂。5. 补充实战软考真题题目以上就是本篇文章的全部内容喜欢的话可以留个免费的关注呦~~~
返回列表