封装是隐藏实现细节,提供公共的访问方式,封装能够带来很多的好处,能提高代码的复用性,能提高代码的安全性,他的设计原则是将不想让外界知道的细节给隐藏起来,提供公共的访问方式。
private是封装的一种体现。
我们举一个例子,抽象出一个模拟收音机类,收音机类中有很多的属性(简化):
package com.henu;
/**
* 模拟的一个收音机
* @author Administrator
*
*/
public class Radio {
// 现在的频道
private static int currentChannel = 1;
// 最后的频道
private static int lastChannel;
// 电量百分比
private static double powerPercent = 1.0;
// 现在的音量
private static int currentVolume = 5;
你拥有这个收音机,观察收音机的外观,有很多的按钮,包括了很多的功能,按钮可能有开机,关机,暂停,恢复,换台,充电等等功能。点击开机,收音机会按照你的指示打开电源,开始播放节目,但是,他里面所做的工作远远没有“按下按钮”那么简单,然而你并不需要去了解这么多,你只需要按下按钮,收音机就会为你服务。而你按下的这些个按钮,就是收音机这个对象对外界提供的访问接口(不讨论Iterface ),收音机有哪些功能,他就有多少个对外的访问接口,这个对用户的接口,就是收音机给用户和收音机内部结构搭起的一座桥梁。这些个对用户的接口,就是声明为public的各个方法,外界(用户)可以通过收音机这个类,去调用这些个public方法。
以下是收音机的一些对外公共方法(简化,举例子):
// 开机
public void powerOn() {
// 1、初始化
init();
// 2、硬件检测
hardWareCheck();
// 3、恢复到上一次的关机频道
recoverLastChannel();
}
// 关机
public void powerOff() {
// 保存频道记录
saveChannel();
// 切断电源
cutOffPower();
}
// 暂停
public void pause() {
// 保存频道记录
saveChannel();
}
// 恢复
public void recover() {
// 恢复到上一次的频道
recoverLastChannel();
}
// 换台
public void switchChannel(int channel) { // 参数 : 选择的台
// 选择台的方法
chooseChannel(channel);
}
// 充电
public void charge() {
// 保存信息
saveChannel();
// 关机
cutOffPower();
// 充电
pushPowerUp();
}
// 增大音量
public void increaseVolume() {
// 音量上升
pushVolumeUp();
}
// 减小音量
public void decreaseVolume() {
// 音量下降
pushVolumeDown();
}
// 搜台
public void searchChannels() {
// 搜台的具体方法
searchAllChannels();
}
可以看到,这些能被用户调用的公共的方法中又调用了很多方法,而这些方法,就是这个收音机类里面的私有方法,这些private方法,不暴露给用户,用户没有办法直接访问这些私有方法。
一些私有方法(简化,举例子):
// 私有的 初始化方法
private void init() {
// 模拟的初始化方法
System.out.println("---开始进行初始化...---");
}
// 私有的 硬件检测
private void hardWareCheck() {
// 模拟的硬件检测方法
System.out.println("---初进入硬件检测...---");
}
// 私有的 恢复上一次频道的方法
private void recoverLastChannel() {
// 模拟恢复上次记录的方法
System.out.println("---恢复上一次收听记录,进入默认频道...---");
if (lastChannel == 1) {
System.out.println("欢迎进入中央一套........");
} else {
System.out.println("欢迎进入中央二套........");
}
}
// 私有的 保存上一次关机的记录
private void saveChannel() {
// 模拟 保存上一次关机的记录的方法
System.out.println("---保存此次的收听记录...---");
// 最后一个台是现在的台
lastChannel = currentChannel;
}
// 私有的 切断电源
private void cutOffPower() {
// 模拟
System.out.println("---切断电源...---");
}
// 私有的 充电的方法
private void pushPowerUp() {
System.out.println("---正在充电...---");
while (powerPercent != 100.0) {
currentVolume += 0.1;
}
System.out.println("---充电完成!---");
}
// 根据选择的台跳转到相应的频道
private void chooseChannel(int channel) {
// 模拟
currentChannel = channel;
switch (currentChannel) {
case 1:
System.out.println("欢迎进入中央一套........");
break;
case 2:
System.out.println("欢迎进入中央二套........");
break;
default:
break;
}
}
// 增加音量
private void pushVolumeUp() {
if (currentVolume < 10) {
currentVolume++;
}
}
// 减小音量
private void pushVolumeDown() {
if (currentVolume > 0) {
currentVolume--;
}
}
// 搜台
private void searchAllChannels() {
//......一些搜台的方法
System.out.println("搜台完毕!有中央一套和中央二套");
}
这些个private方法内,就封装了直接对收音机操作的一些动作。比如说用户要开机,按下开机键,调用powerOn()方法,在外界用户看来,开机,就是按了一下按钮,但是在收音机内部,可能他会首先进行初始化,再进行自身硬件的检测、恢复到上一次关机时候的频道等等,有可能这些动作是几十个几百个,非常地复杂,这些复杂模块都被写在一个一个的私有的方法中,但是用户看不到,这个就是封装。
那么我们为什么要封装呢?我们为什么不能将开机的方法直接写到powerOn()中呢?为什么还要费尽心思地去给他们封装起来,再一一调用呢?
第一,安全性。
假设用户是一个使用收音机的小白,那么,你把这些初始化,检测硬件等等的方法全部放在powerOn()公共方法中,那么就好像是你将收音机内部的许多线路全部暴露给用户了一样,用户不知道你的这些线路干什么用,不知道你放出来的电路板到底作用于什么,他如果强行地去操作,他就有可能对这台收音机进行毁灭性地破坏,这样做是十分危险的,所以这些内部作用的电线,电容,电路板,必须封装在收音机的内部,成为各个模块的private方法以供powerOn()对外的方法调用,用户不需要知道你要初始化,不知道你要检测电路,他只需要知道,按下开机键,开机,这就行了。
第二,复用性
比如收音机和开机功能和暂停时的恢复功能,这两个功能都需要恢复到上一次收音机保存时候的频道,那么,恢复到上一次收听的频道recoverLastChannel( )私有方法就可以被powerOn( )开机方法和recover( )恢复方法同时地调用,这样一来就可以达到代码的复用,如果在开机powerOn( )中直接写下恢复频道的代码,那么你在recover( )方法中依旧需要去再写一遍。
作为一个对象,作为一个完成好的物品或者系统,它的内部可能很复杂,但是他对外暴露给用户的接口,一定不能是复杂的,使用者关心的不是你的系统多么的复杂,多么的令人惊叹,使用者只关心能够在尽可能简单的情况下去使用这个物品,去使用这个系统来完成用户想要的需求。再者说,用户按下一个按钮,或点击一个按钮,随后的功能并不是这个按钮本身提供的,而是按钮作为一个中心触发器,去触发,调度其他的模块之间协作,去完成这个功能。这个按钮就是public的对外方法,是一个桥梁,连接着用户和系统,也连接着用户接口方法和内部模块的桥梁。
作为开发者,我们想要让一个系统安全地,高效地去运行,我们想要用户按照我们自己设定的规则去操作这个系统,就要对系统进行一定的封装,用public的对外接口方法来规范用户的行为,比如收音机,我们不会让用户直接通过操作电阻就改变收音机音量的大小,我们要求用户通过音量键来调节音量的大小,那么这样我们就会把音量currentVolume设为private私有的,只有通过访问increaseVolume()和decreaseVolume()用户才能改变音量,收音机是开发者设计的,所以开发者一定不能让用户直接去改变收音机里的属性和内容,只有通过开发者授权的安全的方式,用户才能进行改变。保证整个系统正常的安全的工作。
以上是对封装的一些的见解。