面向对象:封装与访问控制

封装及其必要性

  1. 封装就是隐藏内部实现的细节,只暴露接口
public class Home {

	public static void main(Strinf[] args) {
	
		Light light1 = new Light();
		light.turnOn();
	
		Light light2 = new Light();
		light2.打开电路1();
		light2.打开电路2();
		light2.打开电路3();
	}
}


public class Light {

	public void turnOn() {
		打开电路1()
		打开电路2()
	    打开电路3()
	}
	
	public void 打开电路1() {
		...
	}
	
	public void 打开电路2() {
		...
	}	
	
	public void 打开电路3() {
		...
	}	
}

Home里面调用Light的方法,产生了耦合。耦合是不好的实践,因为耦合让扩展变得困难,比如开打电路3不需要了, 那么Home里面的代码也要跟着改变。如果把打开电路等都封装到turnOn方法里面,那么这种低耦合确保Home不需要改变。 封装的意义在于对外把暴露出尽可能少的接口

另外一个例子,

Public Class Person {

	public Integer age;
	public String name;
	
	
	public setAge(Integer age) {
		this.age = age
	}
	
	...
	...
}

如果person.age被调用了很多次,突然有一天领导说要大于100的按100算,那么凡是被调用的代码就需要修改无数个地方。 但是如果是通过person.setAge调用的,只需要在Person内部加一个简单的逻辑即可

更加真实的情况是你写的软件作为第三方库被别人用,如果你的一点点的改变需要让别人跟着改变,这样会让人头疼。 软件设计的核心之一是低耦合 不封装是一件非常恐怖的事情

访问控制符

  1. 4种访问限定符,通过限定符来行进封装,取得对外暴露尽可能少的接口

  2. 包的功能 ->

    • 区分同名的类
    • 访问控制(最重要): 提供了一种边界
    • 包之间是没有包含/嵌套关系的

getter、setter方法与JavaBean约定

  1. getter/setter的命名规则,最主要用途在JSON(前后端通信的事实标准),JSON 本质是用字符串来表示对象

  2. 序列化: 内存中的对象 -> 看得见的字符串/字节流 反序列化: 看得见的字符串/字节流 -> 内存中的对象 JSON是序列化/反序列化的一种实现

  3. 对JSON序列化/反序列化的时候,只看getter/setter,与实际的属性无关 如果属性存在,但是没有其getter/setter方法,那么序列化后的JSON不会包含该属性

设计模式实战

  1. 静态工厂方法的好处

    • 是有自定义的名字
    • 可以加入额外的逻辑,不一定每次调用都会创建新的对象
    • 可以返回子类
    • 可以根据输入参数不同返回不同的对象,可以预先定义好static的类, 然后不同情况返回不同的类,这样省时间,也省空间
  2. 静态工厂方法的坏处

    • 不能被子类化,因为是静态的
    • 不容易从文档中找到
  3. Builder模式

类的访问控制符

  1. 怎么样做bridge(黑科技)

  2. JVM只关心类名,类文件在哪里是无所谓的

  3. java 9引入的module,模块化系统,提供更大层面的封装