设计模式之复习基础篇(一)
为什么要写一点东西
以前总是粗略看一遍,也没有深入理解,也记不住什么,过段时间忘得一干二净,所以决定还是记录点东西,方便记忆,利于理解。再此感谢程老师的书籍,通俗易懂。
面向对象基础
类与实例
- 对象:万事万物皆对象,通过感受到,听到,触摸到的东西都是对象。对象是一个自包含实体,用一组可以识别的特性和行为来标示自己。
- 类:类就是具有相同属性和功能的对象的抽象的集合。
- 实例:就是一个真正的对象。
- 实例化:就是创建对象的过程。
构造方法
- 对类进行初始化,构造方法与类同名,无返回值,也不需要void,在使用new的时候进行调用。
方法重载
- 方法名相同,参数不同(个数,类型,顺序)
- 优点:在不改变原有的方法的基础上,新增功能。
属性修饰符
public
:
公开访问权限,属性可以被任何其他类访问,无论它们是否位于同一包中。
private
:
私有访问权限,属性只能在定义它的类内部访问,不允许外部类、子类或同一包中的其他类直接访问。
protected
:
受保护访问权限,属性可以被定义它的类、同一个包中的其他类以及不同包下该类的子类访问。
default
(无修饰符):
如果不使用任何访问修饰符,则属性具有包级访问权限,这意味着它能够被同一个包内的任何类访问,但不能被不同包下的类访问,即使是子类也不可以直接访问。
另外,除了访问控制修饰符外,属性还可以使用以下修饰符:
static
:- 静态修饰符,表示该属性属于类级别,而不是每个实例都拥有一个独立副本。静态属性可以通过类名直接访问,无需创建对象实例。
final
:- 最终修饰符,声明一个属性为常量,一旦赋值后便不可更改。
transient
:- 瞬态修饰符,表示此属性不应被序列化。
volatile
:- 表示该变量是易变的,且保证了多线程环境下的可见性和有序性。
在接口(Interface)中,从Java 8开始可以有默认方法和静态方法,并且接口中的属性默认是 public static final
的,即使你不显式地写出这些修饰符,它们也会自动应用。
封装
- 定义:每一个对象都包含他能操作所需要的所有信息。理解:就是将数据和方法捆绑,通过访问限制控制外部对内部细节的访问。核心思想就是隐藏实现的细节,对外提供公共接口。(家里房子别人不需要如何装修的,只有门和窗户可以访问和空气流通)
- 实现:属性私有化,提供get和set方法,用于读取和修改私有变量的值,从而保证了数据的安全和完整。
- 好处:
- 减少耦合
- 内部实现自由修改
- 类具清晰的对外接口
- 继承
继承
- 定义:是is-a的关系,子类拥有父类除private修饰,构造方法(只能super调用)以外的所有属性和方法,子类除了具备父类的特性外,还具备自己独有的特性。
- 实现:Java中的继承使用
extends
关键字实现,一个类只能直接继承自单个父类(单一继承),但可以通过接口实现多重继承的功能。 - 好处:
- 减少代码冗余
- 继承使得修改或扩展继承实现都较为容易
- 缺点
- 父类变,子类不得不变
- 继承会破坏封装,实现细节暴漏给子类,继承显然是一种强耦合的关系
多态
- 定义:多态指的是同一个接口可以有不同的实现方式,即同一类型的引用指向不同子类型的实例时,表现出不同的行为。多态有两种形式:静态多态(编译时多态)和动态多态(运行时多态)。
- 静态多态主要指方法的重载,发生在编译阶段,同一个类中有多个同名方法,但是参数列表不同。
- 动态多态则涉及到方法的覆盖,当子类重写父类的某个方法时,通过父类引用调用这个方法时会执行子类版本的实现。
- 实现:多态的关键在于抽象类和接口的设计,以及向上转型(Upcasting)的应用。
- 多态的优点体现在增强了程序的灵活性和扩展性,使得代码更容易适应变化的需求,并且能够处理多种类型对象的统一操作,降低了模块间的耦合度。
抽象类
- 定义:
- 使用
abstract
关键字声明一个类为抽象类。 - 抽象类可以包含抽象方法(声明而无实现的方法)和非抽象方法(有具体实现的方法)。
- 抽象类可以有构造方法,用于初始化子类实例时调用。
- 使用
- 特点:
- 不能直接创建抽象类的对象,只能被其他类继承。
- 子类继承抽象类后,必须实现父类中的所有抽象方法,否则子类也需要声明为抽象类。
- 抽象类可以有成员变量,并且这些变量可以具有不同的访问修饰符。
- 应用场景:
- 当多个类共享一些通用的行为和属性,但又无法完整地定义一个共同的逻辑实现时,适合使用抽象类来定义这个基础结构。
接口
- 定义:
- 使用
interface
关键字定义接口。 - 在Java 8及之前版本,接口中的方法默认是抽象的(无实现),并且所有的字段默认为
public static final
(即常量)。 - 自Java 8开始,接口中可以包含静态方法和默认方法(default methods,带有具体实现的方法)。
- 使用
- 特点:
- 接口中不能包含实例变量,只有常量(final修饰)。
- 类可以通过
implements
关键字实现接口,并且必须实现接口中所有的抽象方法。 - 一个类可以实现多个接口,这是Java多继承机制的一种体现(因为Java不支持多继承,但通过接口可以模拟多重继承的效果)。
- 应用场景:
- 当需要定义一组行为规范,使得不同类型的对象能够遵循相同的行为约定时,适合使用接口。
- 接口主要用于设计基于行为的契约,强调的是“做什么”而不是“怎么做”,因此接口更加侧重于描述和规定功能而非具体的实现细节。
总结起来,选择抽象类还是接口主要取决于你的设计目标:如果关注的是类之间的层次关系和部分实现的代码复用,则倾向于使用抽象类;如果更关心定义明确的行为规范和实现多态性,则接口更为合适。自Java 8引入了默认方法和静态方法后,接口的功能得到了进一步增强,有时甚至可以在某种程度上替代抽象类的角色。
接口和抽象类的区别
-
定义方式:
- 抽象类:使用
abstract
关键字声明一个类为抽象类,例如public abstract class AbstractClass {...}
。 - 接口:使用
interface
关键字定义接口,例如public interface InterfaceName {...}
。
- 抽象类:使用
-
继承与实现:
- 抽象类:其他类通过
extends
关键字继承抽象类,并且可以选择性地覆盖或实现抽象方法。 - 接口:类通过
implements
关键字实现接口,并且必须实现接口中所有未实现的方法。自Java 8开始,类可以同时实现多个接口。
- 抽象类:其他类通过
-
包含内容:
- 抽象类:可以包含抽象方法和非抽象方法(具体方法),也可以有字段变量(包括静态变量和实例变量)。抽象类还可以包含构造器,用于子类实例化时初始化共用的属性。
- 接口:只允许包含抽象方法、默认方法(Java 8新增,带有具体实现)、静态方法(Java 8新增)和常量(默认 public static final)。不允许有实例变量,不能包含构造方法。
-
访问修饰符:
- 抽象类中的成员可以是任何访问级别(private, protected, public)。
- 接口中所有的方法默认是
public
的,从Java 9开始,可以显式指定public
;接口中的变量只能是public static final
的,即常量。
-
多继承:
- 抽象类:Java不支持多继承,一个类只能直接继承一个抽象类。
- 接口:Java支持多继承,一个类可以实现多个接口。
-
设计目的与角度:
- 抽象类通常用来定义类族的通用行为,它关注的是对象之间的“is-a”关系,以及部分实现的代码复用。
- 接口主要用于规范一组行为契约,强调的是“能做什么”的能力描述,而不是具体的实现细节,它关注的是对象之间的“has-a”或者“can-do”关系。
- 抽象类是从子类中法向量公共的东西,泛化出子类,子类继承父类,接口不知道子类的存在,方法如何实现还不确认,预先定义。
-
使用场景:
-
类是对对象的抽象对于相似的类对象,可使用抽象类,接口是对行为的抽象,如果行为跨越不同类的对象,使用接口。
-
当需要定义一种类型的基本框架,其中包含一些已知的通用方法并且可能提供某些方法的具体实现时,适合使用抽象类。
-
当需要强制要求不同类型的对象遵守某种协议或提供统一的操作接口时,接口更为合适。
-
大话设计模式 Java溢彩加强版 程杰