重学设计模式-工厂方法模式

1.重学设计模式-带你体验一种不一样的学习之前言篇

2.重学设计模式-工厂方法模式

工厂方法模式

工厂模式提供了一种创建对象的最佳方式,在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。前文介绍过工厂模式属于创建型模式

意图

定义一个创建对象的接口,让其子类自己决定实例滑哪个工厂类,工厂模式使其创建过程延迟到子类进行

通用类图

Product通常是接口,负责定义产品的共性,实现对事物最抽象的定义。ConcreteProduct是product的实现类,主要负责具体如何创建产品。Creator为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。

通用代码实现

csharp 复制代码
public abstract class Product {
   // 产品类的公共方法
   public void method1(){
       // 业务处理逻辑
  }
   // 抽象方法
   public abstract void method2();
}
java 复制代码
public class ConcreteProduct2 extends Product{
   @Override
   public void method2() {
       // 业务处理逻辑
  }
}
java 复制代码
public class ConcreteProduct1 extends Product{
   @Override
   public void method2() {
       // 业务处理逻辑
  }
}
java 复制代码
public abstract class Creator {
   /**
    * 创建一个产品对象,其输入参数类型可以自行设置
    * @param c
    * @return
    * @param <T> 产品类型
    */
   public abstract <T extends Product> T CreateProduct(Class<T> c);
}
java 复制代码
public class ConcreteCreator extends Creator{
   @Override
   public <T extends Product> T CreateProduct(Class<T> c) {
       Product product=null;
       try {
           product = (Product) Class.forName(c.getName()).newInstance();
      } catch (Exception e) {
           throw new RuntimeException(e);
      }
       return (T) product;
  }
}

工厂模式优点

良好的封装性,代码结构清晰一个对象创建是有条件约束的,如一个调用者需要一个具体的产品对象,只要知道产品的类型就可以了,不用知道创建对象的艰辛过程,降低模块间的耦合。其次扩展性非常优秀,上述代码中我们可以看出,在新增产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成。可以看出工厂方法模式是典型的解耦框架,高层模块值需要知道产品的抽象类,其他的实现类都不用关心,符合迪米特法则。不需要的就不用管,也符合依赖倒置原则,只依赖产品类的抽象,也符合里氏替换原则。

工厂模式使用场景

日志记录器:记录日志可能记录到本地硬盘、系统事件、远程服务器等、用户可以选择记录日志到什么地步

数据库访问:当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时

设计一个连接服务器的框架,需要三个协议,"POP3″、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口;

工厂方法模式的扩展

可以缩小为简单工厂模式

当一个模块仅需要一个工厂类,没有必要把它生产出来的时候使用静态的方法就可以了。

升级为多个工厂类

当我们在做一个比较复杂的项目时,经常会遇到初始化一个对象很耗费精力的情况,所有的产品类都放到一个工厂方法中进行初始化会使代码结构不清晰。例如一个产品类有多个具体实现,每个实现类的初始化方法都不相同,如果写在一个工厂方法中,就会导致该方法巨大无比。考虑到需要代码结构清晰,我们可以为每个产品定义一个创建者,每个创建者都独立负责创建对应的产品对象,非常符合单一职责原则。

延迟初始化

何为延迟初始化(Lazy initialization)?一个对象被消费完毕后,并不立刻释放,工厂类保持其初始状态,等待再次被使用。延迟初始化是工厂方法模式的一个扩展应用。

代码示例:

typescript 复制代码
public class ProductFactory {
   private static final Map<String, Product> prMap=new HashMap<>();
   public static synchronized Product createProduct(String type){
       Product product=null;
       if (prMap.containsKey(type)){
           product=prMap.get(type);
      }else {
           if (type.equals("Product1")){
               product=new ConcreteProduct1();
          }else {
               product=new ConcreteProduct2();
          }
           prMap.put(type,product);
      }
       return product;
  }
}

核心思想就是通过HashMap和synchronized 关键字 来保证同一时间只能有一个线程创建并且通过map去判断是否已经创建过了。

工厂方法模式思考

什么时候使用工厂模式以及什么时候使用多个工厂类都是一个我们值得思考的问题。有的时候我们可能使用工厂模式的话会导致类变得特别多,在一定程度上也会导致我们的代码难以维护。但是这个世界上就没有完美的事情嘛。是否使用以及如何使用就根据每个人对于代码的理解,以及系统后续的扩展性和发展来考量了。

欢迎大家在评论区留言,大家对于工厂方法模式个人独特的见解,以及在日常工作中有没有遇见过工厂模式的具体实现。

相关推荐
高频因子挖掘机1 小时前
QuantDash 明明安装成功,为什么 Python 还是无法 import?
后端·github·api
Pniubi8 小时前
HashMap的扩容和树化边界
java·开发语言
Mikko78 小时前
用 Java 复刻了高中时在塞班上玩的「熔岩矿车」:纯 Swing、零依赖、没有一张图片,一个 jar 双击就能玩
java·游戏开发·swing
知了学历孙老师8 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
Java爱好狂.9 小时前
Java初学者如何一周速通SpringBoot!
java·spring boot·后端·spring·高并发·架构师·java面试
秋饼10 小时前
LLM API密钥动态轮换实战:Spring Vault + Spring AI + 多Provider路由
java·ai·技术分享·后端开发
马良神笔11 小时前
2026 年Rag最近技术前沿总结
后端·python·django
程序猿DD11 小时前
同样10美元,OpenDesign和Command Code的DeepSeek V4.1 Flash额度到底有多少?
后端
福兮说11 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
高频因子挖掘机11 小时前
A股量化从日线升级到5分钟线:数据量增加后最先暴露哪些工程问题?
后端·github·api