设计模式之工厂模式(简单工厂,工厂方法,抽象工厂)
前语:在工厂模式中常常会分不清楚(简单工厂和工厂方法,抽象工厂)三者之前的区别,在学习设计模式时也容易混淆,这里对三者进行学习;
工厂模式:顾名思义,客户希望通过工厂(一个或一系列方法)去生产(一个或者一系列产品的实例)
本质:工厂模式是创建者模式,创建对象实例;
一.简单工厂
简单工厂类(SimpleFactory)通过接受参数的形式,调用getShape()方法区得到想要创建的对象;
如图所示:
优点:简单而且粗暴的创建对象,通过参数可以创建任何实现了接口的对象
缺点:(1)当对象类过多,简单工厂就会很臃肿,不利于简单工厂的维护 (2)不符合开放封闭原则,每次增加一个产品子类,就需要修改简单工厂
简单写了一下实现代码:但是不是按照上述UML关系图
产品接口Food的代码如下
1 2 3 | public interface Food { void eat(); } |
实现产品接口的类Apple.class
1 2 3 4 5 6 | public class Apple implements Food { @Override public void eat() { System. out .println( "当前吃是苹果" ); } } |
实现产品接口的类Pear.class
1 2 3 4 5 6 | public class Pear implements Food { @Override public void eat() { System. out .println( "当前正在吃梨子" ); } } |
实现产品接口的类Banana.class
1 2 3 4 5 6 | public class Banana implements Food{ @Override public void eat() { System. out .println( "当前正在吃香蕉" ); } } |
简单工厂方法SimpleFactory.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class SimpleFactory { private Food food= null ; public Food getFood(String FoodName){ if (FoodName== "" || FoodName== null ){ return null ; } switch (FoodName){ case "Banana" : food = new Banana(); break ; case "Apple" : food = new Apple(); break ; case "Pear" : food = new Pear(); break ; default : food= null ; break ; } return food; } } |
方法运行Main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //简单工厂 //1.对象类型 有多种子类 //2.工厂只有 一个 //3.对象的创建延迟到工厂实例中 public class Main { public static void main(String[] args) { //Client 客户来吃水果 Food food = null ; SimpleFactory factory = new SimpleFactory(); food=factory.getFood( "Pear" ); food.eat(); } } |
运行结果:
二.工厂方法
工厂方法为每一个对象提供一种产品提供一个工厂,用于该类的实例化;
如下UML所示为工厂方法。
工厂方法的实现过程代码:
Food接口
1 2 3 | public interface Food { void eat(); } |
Factory接口
1 2 3 | public interface Factory { Food create(); } |
Apple.class类
1 2 3 4 5 6 | public class Apple implements Food { @Override public void eat() { System. out .println( "当前吃是苹果" ); } } |
Banana.class类
1 2 3 4 5 6 7 | public class Banana implements Food{ @Override public void eat() { System. out .println( "当前正在吃香蕉" ); } } |
与之对应的工厂
AppleFactory.class
1 2 3 4 5 6 | public class AppleFactory implements Factory { @Override public Food create() { return new Apple(); } } |
BananaFactory.clsss
1 2 3 4 5 6 | public class BananaFactory implements Factory{ @Override public Food create() { return new Banana(); } } |
工厂方法调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public static void main(String[] args) { Food food = null ; Factory factory = null ; /****************/ String foodName= "Apple" ; switch (foodName){ case "Apple" :factory = new AppleFactory(); break ; case "Banana" :factory = new BananaFactory(); break ; default :factory = null ; } /***************/ food =factory.create(); food.eat(); } |
在调用方法上仍然扩展性不足,但是可以采取反射技术弥补
运行结果:
优点:(1)与简单工厂相比,提高了工厂的扩展性,符合开放封闭原则;
缺点:(2)实现起来较之于简单工厂复杂,无法生存一系列产品
三.抽象工厂
抽象工厂是对于产品系列而言
比如衣服分为帽子,T恤从种类上分,从品牌的角度分为LiNing,Nike,针对这种情况需要创建一个产品族的对象,可以采取抽象工厂的方法
以此为思路,创建的抽象工厂UML为:
具体代码实现
Hat接口
1 2 3 4 | //帽子 public interface Hat { void put(); } |
Shirt接口
1 2 3 4 | //T恤 public interface Shirt { void wear(); } |
Shop接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public interface Shop { Hat SellHat(); Shirt SellShirt(); static Shop setShop(String typeName){ try { Class c =Class.forName(typeName); Shop shop=(Shop) c.newInstance(); return shop; } catch (Exception e) { throw new RuntimeException(); } } } |
LiNingHat.class帽子类
1 2 3 4 5 6 | public class LiningHat implements Hat { @Override public void put() { System. out .println( "穿上李宁的帽子" ); } } |
LiNingShirt.clas李宁的T恤
1 2 3 4 5 6 7 | public class LiningShirt implements Shirt { @Override public void wear() { System. out .println( "穿上李宁的T桖" ); } } |
Nike的帽子NikeHat.class
1 2 3 4 5 6 | public class NikeHat implements Hat{ @Override public void put() { System. out .println( "穿上耐克的帽子" ); } } |
Nike的T恤NikeShirt.class
1 2 3 4 5 6 | public class NikeShirt implements Shirt{ @Override public void wear() { System. out .println( "穿上耐克的T桖" ); } } |
李宁的商店LiNingShop.class
1 2 3 4 5 6 7 8 9 10 11 12 | public class LiningShop implements Shop{ @Override public Hat SellHat() { return new LiningHat(); } @Override public Shirt SellShirt() { return new LiningShirt(); } } |
Nike的商店NikeShop.class
1 2 3 4 5 6 7 8 9 10 11 12 | //Nike商店 public class NikeShop implements Shop { @Override public Hat SellHat() { return new NikeHat(); } @Override public Shirt SellShirt() { return new NikeShirt(); } } |
调用抽象工厂的过程
1 2 3 4 5 6 7 8 9 10 11 12 | public static void main(String[] args) { Hat hat = null ; Shirt shirt = null ; Shop shop =Shop.setShop( "v3.LiningShop" ); hat =shop.SellHat(); shirt =shop.SellShirt(); hat.put(); shirt.wear(); } |
调用结果:
优点:可以针对一系列对象
确定:只针对一系列对象
总结:
简单工厂:针对同一级别的不同对象(扩展性较差)
工厂方法:针对同一级别的固定对象(开放修改接口,扩展性好)
抽象工厂:针对不同系列的全部对象(不支持单个产品扩展,只支持产品族扩展)
使用总结:(1)工厂模式中,工厂类采取的单例模式
(2)工厂类的基类可以是接口也可以是抽象类
(3)调用工厂采取的是指针和引用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义