HeadFirst设计模式笔记

1.当一个超类具有可能在子类中具有变化的方法时,不要使用继承,而是使用接口,单独设计一个该方法的接口,将该方法委托给该类之外的方法类去实现。
例如鸭子超类,鸭子有飞行和呱呱叫方法,但每种不同的鸭子可能会飞也可能不会飞,可能呱呱叫也可能吱吱叫或者不会叫,这时候我们需要设计飞行接口和叫声接口,用不同的具体飞行方法实现类来继承接口,鸭子超类中只需要设定接口参数,之后在具体类中使用多态即可。
此时如果要修改实现也很方便,只需要setFly方法在其中调用具体的飞行方法即可。
在这里插入图片描述
使用组合而不是继承,能使系统具有更大的弹性。
策略模式:定义算法族,分别封装起来,
让他们之间可以相互替换,让算法的变化独立于使用算法的客户。OO原则:1.封装变化 2.多用组合,少用继承 3.针对接口编程,不针对实现编程
良好的OO设计需要可复用,可扩充,可维护

2.观察者模式
定义了对象之间的一对多依赖,当一个对象改变状态时它的所有依赖者都会收到通知并自动更新

松耦合的设计能更好的应对变化,让对象之间的相互依赖降到最低

在这里插入图片描述

例如我们要实现一个气象站和观察系统,有许多不同的布告板,布告板实时更新气象站的观察数据,如果挨个推送的话非常麻烦,这时候我们就可以使用观察者模式,气象数据类继承具有设置观察者和提醒观察者方法的接口,布告板类继承观察者接口,当气象数据类更新数据时,就会通知所有观察者数据更新了。就像报志发行和订报纸的人的关系一样,观察者可以取消或者增加订阅,而发送数据的类不会因为观察者的增加或减少随意改动。
在这里插入图片描述
java具有内置的观察者类observer类,可以改用观察者在通知改变时从主题处选择性拉取数据而不是主题自动push所有更新数据的方式。但问题在于observers是一个类而不是接口,这限制了它的使用和复用。

3.装饰模式
动态的将责任附加到对象上,想要扩展功能,装饰者是有别于继承的另一种选择。
设计原则:类应该对扩展开放,对修改关闭
在这里插入图片描述
例如计算咖啡的价格,对于不同的咖啡我们可能会加奶泡,摩卡等,这时候对于不同下需要我们不应该滥用继承,而是可以应用装饰者模式,关键在于装饰者超类和被装饰者要继承同一个抽象超类,以确保类型不变。比如咖啡和调料都应该继承自饮料超类,这样最后经过层层包装,我们得到的仍然是一杯饮料。

在这里插入图片描述
java中的IO类就应用了装饰者模式,例如LineNumberInputStream/BufferedInputStream/FileInputStream
都继承自FilterInputStream,一个抽象的装饰类

缺点:装饰者模式可能导致设计中有大量的小类

4.工厂模式
处理创建对象的细节,将创建对象的行为封装在子类中,这样客户程序中关于超类的代码就和子类对象创建代码解耦了。

abstract Product factoryMethod(String type)
*工厂方法是抽象的,所以依赖子类来处理对象的创建
*工厂方法必须返回一个产品。超类中定义的方法通常使用到工厂方法的返回值。
*工厂方法将客户和实际创建具体产品的代码分隔开来。
*工厂方法可能需要参数(也可能不需要)来指定所要产品。

例如披萨店对象,需要创建披萨,并对披萨进行烘烤,切片和包装。但不同的加盟店有不同风味的披萨菜单,所以我们可以在抽象披萨店类中定义抽象方法createpizza,以及在不同披萨店中都相同的后续方法(该方法不关心传入的是什么披萨,只知道这是一个可以加工的披萨对象),这样实现具体子类时只需要重写抽象方法createpizza即可。

在这里插入图片描述
在这里插入图片描述
工厂方法模式:定义一个创建对象的接口,但由子类决定实例化的类是哪一个。工厂方法让类把实例化推迟到了子类。

在这里插入图片描述
注意简单工厂和工厂方法是不同的,虽然看起来很相似,但是简单工厂是将全部的事情在一个地方处理完了,而工厂方法则是创建一个框架让子类决定如何实现。简单方法只是将创建对象的过程封装起来,而不具备工厂方法的弹性。

依赖倒置原则:要依赖抽象而不是具体类
如何在面向对象设计中不违反依赖倒置原则:
*变量不可以持有具体类的引用:如果使用new就会持有具体类的引用,可以用工厂方法进行改进
*不要让类派生自具体类:如果派生自具体类就会依赖具体类,应该派生自一个抽象(接口/抽象类)
*不要覆盖基类中已实现的方法:如果覆盖则说明基类不是一个真正适合被继承的抽象,基类中已实现的方法应该由所有子类共享。

抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
在这里插入图片描述

从抽象工厂中会派生处具体的工厂,这些工厂产生相同的产品,但是产品的实现不同。在抽象工厂中经常会使用工厂方法来实现具体工厂。
工厂方法使用继承,把对象的创建委托给子类,子类实现工厂方法来创建对象。
抽象工厂使用对象组合,对象的创建被是现在工厂接口所暴露出的方法中。

5.单件模式 Single Pattern
确保一个类只有一个实例,并提供一个全局访问点。
在这里插入图片描述

设置getInstance来确保该类只有一个实例化对象。
但对于多线程程序来说getInstance()可能会拖垮性能,因为每一次访问都会同步一次,而实际上只有第一次执行此方法时才需要真正同步。
解决方法:1.如果能接受额外负担则保持不变
2.急切实例化:在静态初始化器中创建单价,保证线程安全。
3.用双重检查加锁,在getInstance()中减少使用同步。首先检查实例是否已经创建了,如果尚未创建才会进行同步。

6.命令模式
将“请求”封装成对象以便使用不同的请求,队列和日志来参数化其他对象,命令模式也支持可撤销的操作。
首先让所有命令对象实现相同的包含一个方法的接口,例如方法execute();
写具体的命令:比如命令电灯开启:实现命令接口,在实现的方法中写要电灯打开的方法。在遥控器类中加入命令具体类,就可以调用让电灯开启的命令了。

在这里插入图片描述
由于命令对象和执行命令的对象解耦,需要扩展功能模块的时候也很方便。比如要给遥控器加上撤销功能,只需要在command类中加上undo方法即可。
另外还可以使用宏命令来一次执行多个命令。命令模式还可以用来记录日志和事件等。

7.适配器模式
定义:将一个类的接口,转换成客户期望的另一个接口。
用一个类来让某个接口去适配另一个接口,该类就是适配器类,比如想把一只火鸡包装成鸭子类,那么只要让火鸡适配器类实现鸭子接口即可,内在是火鸡,但却能实现鸭子的方法。
在这里插入图片描述

客户端使用适配器模式的过程:
1.客户通过目标接口调用适配器的方法对适配器发出请求
2.适配器使用被被适配者接口把请求转换成被适配者的一个或多个调用接口
3.客户接收到调用的结果,但并未察觉是适配器在起转换作用

对象适配器

类适配器
类适配器需要多重继承,在java中无法实现

类适配器通过继承实现适配,对象适配器通过组合来实现适配

8.外观模式
通过实现一个提供更合理的接口的外观类,你可以将一个复杂的子系统变得更容易使用。

外观不止简化了接口,也将客户从组件的子系统中解耦。
外观模式
最少知识原则:减少对象之间的交互
在设计中不要让太多的类耦合在一起,免得修改系统中的一部分会影响到其他部分

设计原则:在该对象的方法内我们只应该调用属于以下范围的方法:
1.该对象本身
2.被当作方法的参数而传递的进来的对象(如果某对象是调用其他方法的返回结果,不要调用该对象的方法)
3.此方法所创建或实例化的任何对象
4.对象的任何组件(HAS-A)

9.模板方法
定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。

例如冲泡咖啡的步骤是:烧热水->冲咖啡->倒进杯子->加牛奶
冲泡茶的步骤是烧热水->冲茶->倒进杯子->加柠檬
此外二者还都具有预先准备方法包括以上四个步骤

我们不仅可以把相同的步骤一和步骤三的具体方法加到“冲调咖啡因饮料”抽象类中,还可以把不同的预先准备方法抽象,只需要把步骤二和四分别抽象成“冲泡”,“加调料”抽象方法,再在茶和咖啡子类中具体实现即可。

模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

模式方法
在这里插入图片描述

在这里插入图片描述

抽象类中的钩子方法可以让子类有能力对算法的不同点进行挂钩。
子类可以选择是否实现钩子的方法。

钩子与抽象方法的区别就在于,当子类必须实现某个方法时就定义成抽象方法,如果该方法是子类可选的就使用钩子。
钩子可以让子类选择算法的实现与否,以及让子类有机会对模板方法中某些即将发生的步骤作出反应。

好莱坞原则:不要调用我们,我们会调用你
该原则可以防止依赖腐败,阻止底层组件高层组件和边侧组件发生过于复杂的依赖。高层组件对于底层组件的方式应该是好莱坞原则。

java中的比较器就是模板模式的应用

9.迭代器模式
假如有一家使用数组菜单的早餐店和一家使用集合菜单的午餐店要合并,然而厨师都不愿意修改菜单的实现,此时女招待遍历菜单时就需要同时使用数组类和集合类,会产生依赖导致不容易扩展和修改。我们可以为两种菜单实现有hasNext()方法和next()方法的迭代器接口,这样女招待类只需要和迭代器类产生交互了。
在这里插入图片描述
但此时女招待仍然要和两种菜单类交互,我们可以把两种菜单类抽取出包含createIterator()方法的Menu接口,女招待就只需要管辖两个接口了。
在这里插入图片描述

定义:迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示。

在这里插入图片描述
设计原则:一个类应该只有一个引起类变化的原因
内聚:用来度量一个类或者模块紧密地达到单一目的或责任。
高内聚:模块被设计成支持一组相关的功能
低内聚:模块被设计成支持一组不相关的功能

10.组合模式
当我们想在某个菜单中插入子菜单应该怎么办?
组合模式允许你将对象组合成树形来表现整体/部分层次结构,组合能让客户以一致的方式处理个别对象以及对象组合。

使用组合结构,我们能把相同的操作应用在组合和个别对象上,换句话说在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。
在这里插入图片描述
在这里插入图片描述

所有组件都必须实现MenuComponent接口,然而叶节点和组合结点的角色不同,所以有些方法可能并不适合某种节点,此时应当抛出运行时异常。

11.状态模式
假如我们需要写一个糖果机程序,有四种状态分别是“没有硬币”,“有硬币”,“有糖果”,没糖果“,根据运行的流程糖果机会在这几种状态之间转换。如果我们用静态数字分别表示这些状态,那么程序的扩展性就会很差,比如我们想为糖果机加入一个赢家状态,投币时有10%的可能掉出2颗糖果,由于之前的设计耦合太紧密,想要增加新功能就会变得很麻烦。

想要得到一个容易维护的设计,我们应该定义一个State接口,在接口内,糖果机的每个动作都有一个对应的方法,为机器中的每个状态实现状态类,这些类将负责在对应状态下进行机器行为,最后将糖果机的动作委托到状态类。

在这里插入图片描述
状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。这个模式将状态封装成为独立的类,并将动作委托到代表当前状态的对象。对象的行为会随着状态的改变而改变。

在这里插入图片描述

12.代理模式
远程代理:远程对象的本地代表。可以作为另一个JVM上对象的本地代表。调用代理的方法会被代理利用网络转发到远程执行,并且结果会通过网络返回给代理,再由代理将结果转给客户。
在这里插入图片描述
代理模式:为另一个对象提供一个替身或占位符以控制这个对象的访问
在这里插入图片描述
虚拟代理:作为开销大的对象的代表,直到我们真正需要一个对象的时候才去创建它。当对象再创建前和创建中时,由虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。
在这里插入图片描述

动态代理:java.lang.reflect包中有代理支持,利用这个包我们可以在运行时动态的创建代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。

13.复合模式
模式通常被一起使用,并被组合在同一个设计解决方案中
复合模式在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。

例如 我们想创建一个鸭子模拟器,首先有一只鹅想被包装成鸭子,那么我们只需要使用适配器模式将鹅包装在继承了呱呱叫接口的鹅适配器中即可。假如我们想计算鸭子叫的次数,我们只需要使用装饰者模式建立继承了Quackable()接口的QuackCount。假如我们想批量创建能计数的鸭子或者不能计数的鸭子,只需要应用工厂模式和抽象工厂。
如果我们想更好的管理鸭子,可以使用组合模式将Quackable集合成一个群,遍历时使用迭代器模式。如果我们想监测鸭子叫,只需要使用观察者模式。
在这里插入图片描述
认识MVC模式:
在这里插入图片描述
用户和视图交互-控制器要求模型/视图改变状态-模型状态改变时,模型会通知视图-视图向模型询问状态
MVC模型使用了哪些设计模式?

在这里插入图片描述

模式分类:
1.创建型:涉及到将对象实例化,提供一个方法将客户从所需实例化的对象中解耦,例如抽象工厂,工厂模式,Builder,单件模式,Prototype

2。行为型:涉及到类和对象如何交互及分配职责
例如迭代器,观察者,命令模式,状态模式,策略模式,模板模式,Visitor,Mediator,Interpreter,Chain ofResponsibility

3.结构型:把类或对象组合到更大的结构中
例如代理模式,外观模式,适配器模式,组合模式,装饰模式,Flyweight,Bridge

另一种分类方式是按照模式处理的是类还是对象进行分类
1.类模式:描述类之间的关系如何通过继承定义,关系在编译时建立,包括工厂模式,适配器模式,模板模式,Interpreter

2.对象模式:描述对象之间的关系,主要利用组合定义,对象模式的关系通常在运行时建立,更加动态而有弹性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Head First设计模式》是一本设计模式学习的畅销书籍。这本书的作者以幽默风格和易于理解的语言,引导读者深入了解面向对象设计的基础知识和常见设计模式的应用。 《Head First设计模式》首先介绍了面向对象设计原则,如开闭原则、依赖倒置原则和单一职责原则等。它强调了设计模式的重要性,这些模式是在常见的软件开发场景中提供解决方案的经验总结。 接着,书中详细介绍了23个经典的设计模式,分为创建型模式、结构型模式和行为型模式三个大类。每个模式都通过生动的例子和图表进行解释,使读者能够更好地理解其应用场景和使用方法。同时,还提供了一些实际案例,帮助读者将学到的知识应用到实际项目中。 《Head First设计模式》以问题驱动的方式进行讲解,通过解决具体的问题来引导读者理解模式的思想和用法。这种方式使得学习变得更加有趣和互动,读者可以通过参与问题的解决过程来更好地理解模式的实际应用。 总的来说,这本书是一本通俗易懂的设计模式入门教材。它以轻松幽默的方式向读者介绍了设计模式的基本概念和常见应用。读者通过阅读这本书,能够对设计模式有一个清晰的理解,并能够在实际项目中灵活运用。无论是初学者还是有一定经验的开发者,都能从中收获实用的知识和提升自己的设计能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值