[Java基础] 设计模式之工厂模式_工厂模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。(

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:xhs1999xhs (备注Java)
img

正文

CSDN话题挑战赛第2期
参赛话题:学习笔记

写在前面

作者简介:鲸海鹿林

博客主页:鲸海鹿林的主页

名言警句:keep calm and carry on

本系列参照HeadFirst系列设计模式这本书,换言之,是 HeadFirst设计模式这本书的读书笔记,让我们一起学习吧!

new的思考

识别变化的方面

当需要增加更多的类型……

建立一个简单比萨工厂

重做PizzaStore类

定义简单工厂

已有的做法……

但是你想要多一些质量控制……

给比萨店使用的框架

允许子类做决定

订购一个比萨​编辑

认识工厂模式(Factory Method Pattern)

另一个观点:平行的类层级

​编辑定义工厂方法模式

对象依赖

依赖倒置原则

原则的应用

疑惑——为什么叫依赖倒置?

倒置你的思考方式

指导方针——帮助你遵循该原则

回到比萨店……

建造原料工厂

创建纽约原料工厂

​编辑重做比萨

再回到比萨店

我们做了什么?

订购更多的比萨

定义抽象工厂模式

模式访谈

模式比较


new的思考

这里有一些要实例化的具体类,究竟实例化哪一个类,要在运行时由一些条件来决定。当看到这样的代码,一旦有变化或扩展,就必须重新打开这段代码进行检查和修改。通常这样修改过的代码将造成部分系统更难维护和更新,而且也很容易犯错。

识别变化的方面

假设你有一个比萨店,身为对象村内最先进的比萨店主人,你的代码可能这么写:

Pizza orderPizza(){
    Pizza pizza = new Pizza();

    pizza.prepare();
    pizza.break();
    pizza.cut();
    pizza.box();
    return pizza;
}

但是你需要更多的比萨类型……所以必须增加一些代码,来决定适合的比萨类型,然后再制造比萨:

Pizza orderPizza(String type) {
    Pizza pizza;

    if(type.equals("cheese")){
        pizza = new CheesePizza();
    }else if(type.equals("greek")){
        pizza = new GreekPizza();
    }else if(type.equals("pepperoni")){
        pizza = new PepperoniPizza();
    }

    pizza.prepare();
    pizza.break();
    pizza.cut();
    pizza.box();
    return pizza;
}

当需要增加更多的类型……

你发现你所有的竞争者都已经在他们的菜单中加入了一些流行风味的比萨:Clam(蛤蜊) Pizza、Veggie(素食) Pizza。很明显,你必须要赶上他们,所以也要把这些风味加进你的菜单中。而最近Greek Pizza卖的不好,所以你决定要将它从菜单中去掉:

Pizza orderPizza(String type) {
    Pizza pizza;

    if(type.equals("cheese")){
        pizza = new CheesePizza();
//    }else if(type.equals("greek")){
//        pizza = new GreekPizza();
    }else if(type.equals("pepperoni")){
        pizza = new PepperoniPizza();
    }}else if(type.equals("clam")){
        pizza = new ClamPizza();
    }}else if(type.equals("veggie")){
        pizza = new VeggiePizza();
    }

    pizza.prepare();
    pizza.break();
    pizza.cut();
    pizza.box();
    return pizza;
}

很明显,如果实例化某些具体类,将使orderPizza()出问题,而且也无法让orderPizza()对修改关闭;但是,现在我们已经知道那些会改变,哪些不会改变,该是封装出马的时候了。

还有一些细节有待补充,比方说,原本在orderPizza()方法中的创建代码,现在该怎么写?现在就来为比萨店实现一个简单的比萨工厂。

建立一个简单比萨工厂

先从工厂本身开始,我们要定义一个类,为所有比萨封装创建对象的代码。

public class SimplePizzaFactory{
    Pizza createPizza(String type) {
        Pizza pizza = null;

        if(type.equals("cheese")){
            pizza = new CheesePizza();
        }else if(type.equals("pepperoni")){
            pizza = new PepperoniPizza();
        }}else if(type.equals("clam")){
            pizza = new ClamPizza();
        }}else if(type.equals("veggie")){
            pizza = new VeggiePizza();
        }
        return pizza;
    }
}

重做PizzaStore类

是时候修改我们的客户代码了,我们所要做的是仰仗工厂来为我们创建比萨,要做如下的改变:

public class PizzaStore{
    SimplePizzaFactory factory;
    
    public PizzaStore(SimplePizzaFactory factory){
        this.factory = factory;
    }

    public Pizza orderPizza(String type){
        Pizza pizza;
        
        pizza = factory.createPizza(type);

        pizza.prepare();
        pizza.break();
        pizza.cut();
        pizza.box();
        return pizza;
    }

}

定义简单工厂

再提醒一次:在设计模式中,所谓的“实现一个接口”并不一定表示写一个类,并利用implement关键词来实现某个Java接口。实现一个接口泛指实现某个超类型(可以是类或接口)的某个方法。

已有的做法……

如果利用SimplePizzaFactory,写出三种不同的工厂,分别是NYPizzaFactory、ChicagoPizzaFactory、CaliforniaPizzaFactory,那么各地加盟店都有适合的工厂可以使用,这是一种做法。

让我们看看未来会变成什么样……

但是你想要多一些质量控制……

在推广SimpleFactory时,你发现加盟店的确是采用你的工厂创建比萨,但是其他部分,却开始采用他们自创的流程:烘烤的做法有所差异、不要切片、使用其他厂商的盒子。

再想想这个问题,你真的希望能够建立一个框架,吧加盟店和创建比萨捆绑在一起的同时又保持一定的弹性。

在我们稍早的SimplePizzaFactory代码之前,制作比萨的代码绑在PizzaStore里,但这么做却没有弹性。那么,该如何做才能够吃掉比萨又保有比萨呢?

给比萨店使用的框架

有个做法可让比萨店制作活动局限于PizzaStore类,而同时又能让这些加盟店依然可以自由地制作该区域的风味。

所要做的事情,就是把createPizza()方法放回到PizzaStore中,不过要把它设置成“抽象方法”,然后为每个区域风味创建一个PizzaStore的子类。

允许子类做决定

别忘了,PizzaStore已经有一个不错的订单系统,由orderPizza()方法负责处理订单,而你希望所有加盟店对于订单的处理都能够一致。

各个区域比萨店之间的差异在于他们制作比萨的风味,我们现在要让createPizza()能够应对这些变化来负责创建正确种类的比萨。做法是让PizzaStore的各个子类负责定义自己的createPizza()方法。所以我们会得到一些PizzaStore具体的子类,每个子类都有自己的比萨变体,而仍然适合PizzaStore框架,并使用调试好的orderPizza()方法。

 

当orderPizza()调用createPizza()时,某个比萨店子类将负责创建比萨。做哪一种比萨?当然是由具体的比萨店来决定。

那么,子类是实时做出这样的决定吗?不是,但从orderPizza()的角度来看,如果选择在NYStylePizzaStore订购比萨,就有这个子类决定。严格来说,并非由这个子类实际做决定,而是由顾客决定到哪一家风味的比萨店才决定了比萨的风味。

订购一个比萨

认识工厂模式(Factory Method Pattern)

工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。

另一个观点:平行的类层级

我们已经看到,将一个orderPizza()方法和一个工厂方法联合起来,就可以成为一个框架。除此之外,工厂方法将生产知识封装进各个创建者,这样的做法,也可以被视为是一个框架。

定义工厂方法模式

对象依赖

依赖倒置原则

原则的应用

疑惑——为什么叫依赖倒置?

倒置你的思考方式

指导方针——帮助你遵循该原则

回到比萨店……

建造原料工厂

创建纽约原料工厂

重做比萨

再回到比萨店

我们做了什么?

订购更多的比萨

定义抽象工厂模式

模式访谈

模式比较

最后

ActiveMQ消息中间件面试专题

  • 什么是ActiveMQ?
  • ActiveMQ服务器宕机怎么办?
  • 丢消息怎么办?
  • 持久化消息非常慢怎么办?
  • 消息的不均匀消费怎么办?
  • 死信队列怎么办?
  • ActiveMQ中的消息重发时间间隔和重发次数吗?

ActiveMQ消息中间件面试专题解析拓展:

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


redis面试专题及答案

  • 支持一致性哈希的客户端有哪些?
  • Redis与其他key-value存储有什么不同?
  • Redis的内存占用情况怎么样?
  • 都有哪些办法可以降低Redis的内存使用情况呢?
  • 查看Redis使用情况及状态信息用什么命令?
  • Redis的内存用完了会发生什么?
  • Redis是单线程的,如何提高多核CPU的利用率?

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


Spring面试专题及答案

  • 谈谈你对 Spring 的理解
  • Spring 有哪些优点?
  • Spring 中的设计模式
  • 怎样开启注解装配以及常用注解
  • 简单介绍下 Spring bean 的生命周期

Spring面试答案解析拓展

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


高并发多线程面试专题

  • 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
  • Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
  • Java 中 wait 和 sleep 方法有什么区别?
  • 如何在 Java 中实现一个阻塞队列?
  • 如何在 Java 中编写代码解决生产者消费者问题?
  • 写一段死锁代码。你在 Java 中如何解决死锁?

高并发多线程面试解析与拓展

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


jvm面试专题与解析

  • JVM 由哪些部分组成?
  • JVM 内存划分?
  • Java 的内存模型?
  • 引用的分类?
  • GC什么时候开始?

JVM面试专题解析与拓展!

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:xhs1999xhs(备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
数据完整性。

  • Java 中 wait 和 sleep 方法有什么区别?
  • 如何在 Java 中实现一个阻塞队列?
  • 如何在 Java 中编写代码解决生产者消费者问题?
  • 写一段死锁代码。你在 Java 中如何解决死锁?

高并发多线程面试解析与拓展

[外链图片转存中…(img-boLT2GuM-1713695937464)]


jvm面试专题与解析

  • JVM 由哪些部分组成?
  • JVM 内存划分?
  • Java 的内存模型?
  • 引用的分类?
  • GC什么时候开始?

JVM面试专题解析与拓展!

[外链图片转存中…(img-9bg4kNbH-1713695937464)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:xhs1999xhs(备注Java)
[外链图片转存中…(img-DrK5R82P-1713695937464)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 21
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值