HeadFirst设计模式笔记

时间:2022-12-26 09:59:00

设计模式(原则)

将设计模式装进大脑里,然后在你的设计和已有的应用中,寻找何处可以使用它们。以往是代码复用,现在是经验复用。

设计原则1:封装变化。找出应用中可能需要变化之处,把它们独立出来,不需要和那些不需要变化的代码混合在一起。(将会变化的部分取出并“封装”起来,好让其他部分不会受到影响。

设计原则2:针对接口编程,而不是针对实现编程。(“针对接口编程”的真正意思是“针对超类型(supertype)编程”,超类型可以是抽象类“或”接口。

设计原则3:多用组合,少用继承。

设计原则4:为了交互对象之间的松耦合设计而努力。(松耦合设计能让我们建立有弹性的OO系统,能够应对变化,因为对象之间的互相依赖降到了最低水平。)

设计原则5:类应该对扩展开放,对修改关闭。(我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可以搭配新的行为。这样的设计具有弹性可以应付改变,可以接受新的功能来应对改变的需求)

设计原则6:要依赖抽象,不要依赖具体类。(不让高层组件依赖低层组件,而且,不管高层或低层组件,“两者”都应该依赖于抽象)。

设计原则7:最少知识原则:只和你的密友交谈。(在设计中,不要让太多的类耦合在一起,免得修改系统中一部分,会影响到其他部分。)关键:不要调用从另一个调用中返回的对象的方法,也就是不要向另一个对象的子部分发请求。

设计原则8:好莱坞原则。(别调用(打电话给)我们,我们会调用(打电话给)你)。

注意:
1. 有一些面向对象的原则,适用于所有的模式。当无法找到合适的模式来解决问题时,采用这些原则可以达到目的。
2. 在设计模式中,“实现一个接口”并“不一定”表示“写一个类,并利用implement关键词来实现某个java接口”。“实现一个接口”泛指“实现某个超类型(可以是类或接口)的某个方法”。

策略(Strategy)模式

定义: 定义了算法簇,分别将其封装起来,让它们之间可以相互替换,该模式让算法的变化独立于使用算法的客户。(当需要给朋友留下深刻的印象,或者想影响关键主管的决策时,可以使用“这个”定义。)

  1. 抽象方法的作用:在该类中不用实现它,或者说在该类中不确定该如何实现它,它是用来被重载的方法。(比如有一个鸭子类,它的外观都不相同,display()方法可以定义为抽象的)
  2. 当涉及“维护”时,为了“复用”(reuse)目的而使用继承,结果并不好。(比如当在父类鸭子中加入fly()方法时,那些不会飞的鸭子(橡皮鸭)也会同时继承)。
  3. 当使用Flyable接口来实现时(只有会飞的鸭子才能继承Flyable接口),可以解决上面问题,但是又会导致代码无法复用的问题。

实例代码—->headfirst/strategy

菜鸟教程策略模式

观察者(Observer)模式

注意:当试图使用观察者模式时,可以比拟出版者和订阅者的关系。

定义:定义了对象之间的一对多的依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

观察者模式有两种实现方式:
1. 自己实现Subject接口和Observer类。
2. java.util包内有最基本的Obserer(Subject)接口与Observable(Observer)类,(同时提供了推(push)和拉(pull)两种方式来传送数据)。push方式被认为更正确。

注意: 不要依赖观察者被通知的次序。(java自带的观察者模式,Observable是一个类,它会自己实现notifyObservers()方法,该方法会自定义其观察者的顺序)

应用:在JavaBeans和Swing中也使用了观察者模式。
实例代码—->headfirst/observer
菜鸟教程观察者模式

装饰者(Decorator)模式

定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

注意: 通常装饰者模式采用抽象类,但是在java中可以使用接口。
应用: 在java I/O中使用了装饰者设计模式。

实例代码—->headfirst/decorator
菜鸟教程装饰者模式

工厂(Factory)模式

应用:
1. Collection中的iterator方法
2. JDBC数据库开发

1.简单工厂

注意:简单工厂不是一个设计模式,它更像是一种编程习惯。

静态工厂: 利用静态方法定义一个简单工厂。

优点:不需要使用创建对象的方法来实例化对象。
缺点:不能通过继承来改变创建方法的行为。(因为静态方法只和类相关,不能通过继承来重写该方法)。
实例代码—->headfirst/factory/pizzas
菜鸟教程工厂模式

2.工厂方法

定义:定义一个创建对象的接口,但是由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。(所谓的“决定”,并不是指模式允许子类本身在运行时做出决定,而是指在编写创建者类时,不需要知道实际创建的产品是哪一个。)
实例代码—->headfirst/factory/pizzafm
菜鸟教程工厂模式

3.抽象工厂

定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确的指定具体类。

实例代码—->headfirst/factory/pizzaaf
菜鸟教程抽象工厂模式

要点:
1. 所有的工厂都是用来封装对象的创建。
2. 简单工厂,虽然不是真正的设计模式,但依然是一个简单的方法,将客户程序从具体类中解耦。
3. 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。
4. 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。
5. 所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。
6. 工厂方法允许类将实例化延迟到子类中进行。
7. 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。
8. 依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象。
9. 工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。

单件模式

定义:确保一个类只有一个实例,并提供一个全局访问点。(注意处理多线程的情况)

饿汉式: 类一加载就创建对象
懒汉式: 用的时候才去创建对象

应用:Runtime类中提供了恶汉式单例模式,jdk都是用恶汉式,我们开发时就要使用恶汉式(单面试的时候面试官叫你写一个单例模式那你要写懒汉式,因为他要考你的是线多程安全问题)
实例代码—->headfirst/singleton
菜鸟教程单例模式

适配器模式

定义:将一个类的接口,转换成客户期望的另一各接口。适配器让原本接口不兼容的类可以合作无间。

使用场景:当需要使用一个现有的类而其接口并不符合你的需要时,就使用适配器。

注意:适配器模式有两种形式,对象适配器和类适配器。而类适配器需要用到多重继承。

应用:将Enumeration(旧世界的枚举类)适配到Iterator(新世界的迭代器)。
实例代码—->headfirst/adapter
菜鸟教程适配器模式

外观模式

定义:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

使用场景:当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观。

实例代码—->headfirst/facade
菜鸟教程外观模式

对比:
1. 适配器将一个对象包装起来以改变其接口;
2. 装饰者将一个对象包装起来以增加新的行为和责任;
3. 外观将一群对象包装起来以简化其接口。

模板方法模式

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

注意:
1. 为防止恶意操作,一般模板方法都加上 final 关键词。
2. 策略模式和模板方法模式都封装算法,一个用组合,一个用继承。
3. 工厂方法是模板方法的一种特殊版本。

钩子:钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。

使用场景:
1. Arrays.sort()排序算法(利用Comparable接口)
2. Swing窗口程序
3. Applet

实例代码—->headfirst/templatemethod
菜鸟教程模板方法模式