前言:封装的定义是把一类事情封装起来,使得使用者不必在意内部具体逻辑,只需要关心如何使用即可。降低使用成本,易于管理,扩展性高,一定程度还可以减少重复代码增加代码复用性。
1、封装记录
封装记录并不是要封装日志记录,而是封装一组变量,它针对的是会修改的变量组。如果假设三个变量,start、end、count是会用到的一组变量,如果这是一个固定值,就可以这么定义三个变量或者写成静态变量或常量,如果是一组会被改变的变量,可能会被展示成这样
// 逻辑代码中
var data = {"start": 0, "end": 100, "count": 100}
// -----表示在后续的逻辑中可能会对上述的变量进行修改
data["start"]++;
data["count"]++:
以上这种方式被称为记录,记录变量的值。而封装记录,就是把这个变量封装成对象。封装就是希望人们不必追究存储的过程和细节,由于对于这种可以被更改的变量来说,一个变量到处修改是一个难维护的事,封装到对象中更合适,提供一个公共的set方法,遵循对象的规则去set和get。
class Condition {
Condition(data) {
this.start = data['start']
this.end = data['end']
this.count = data['count']
}
getStart();
getEnd();
getCount();
setStart(start);
setEnd(end);
setCount(count);
incCount();
}
2、封装机集合
class Person {
// set课程列表
setCourses(couresesMap);
// 获取课程列表
getCourses();
}
以上的代码,在person这个类中有set和get来管理着一个集合,
person = new Person();
sourcesData = person.getSourcesMap();
sourcesData.add("一个新的数据")
这样通过get获取到了集合,再去操作修改集合,这种修改它的封装对象却不知道,这样就破坏了封装。所以要想办法把数据的维护放到对象中,类似这样:
class Person {
// set课程列表
setCourses(couresesMap);
// 获取课程列表
getCourses();
// 增加课程
addCourse(course);
// 移除指定课程
removeCourse("xxx");
// 课程排序
sortCourse();
}
3、以对象取代基本类型
在开发的初期,经常会定义一些变量表示某些情况,比如各种status之类的标识某种状态之类的。随着开发量的增加可能又会产生各种变种的需求。比如根据status的状态决定禁止某些权限,这一类的情况很容易产生很多重复代码增加使用成本。
所以这个以对象取代基本类型的概念就是指当发现某一个定义的使用不仅仅是完成一个事情时,就应该给他创建一个类去封装。这样无论后面怎么发展都可以很好的适应。
class Person{
getStatus();
enablePay() {
return this.status === 300;
}
}
4、以查询取代临时变量
在上一节有这样的一个案例,
function getPrice(order) {
// 变量提炼,
// 把基础价格提炼出来
const basePrice = order.num * order.price
// 把折扣费用提炼出来
const discountPrice = Math.max(0, order.num - 500) * order.price * 5%
// 再把运费提炼出来
const shippingPrice = Math.min(basePrice * 1%, 100)
return basePrice - discountPrice + shippingPrice
}
这个案例站在独立函数的角度看起来也还可以,但是站在对象的角度还可以进一步优化一下,以下是优化:
class Order(){
Order(data) {
this.num = data.num;
this.price = data.price;
}
// 把各种费用封装
basePrice() {
return this.num * order.price;
}
discountPrice() {
return Math.max(0, this.num - 500) * this.price * 5%
}
shippingPrice() {
return Math.min(this.basePrice() * 1%, 100);
}
getPrice(){
// 替代掉临时变量,
return this.basePrice() - this.discountPrice() + this.shippingPrice();
}
}
5、提炼类
提炼类这个概念是说,当我们已经封装了一个类了,但是随着扩张的过程中,有一些小方向逐渐增长成块了,比如
class Person{
getName();
getAge();
getOfficeTel(); // 办公室电话
getOfficeAreaNumbe(); // 办公室电话区号
}
很明显在Person形成了Office相关的多个方向,就可以考虑把这个方向提炼出来变成一个独立的类比如
class Person{
getName();
getAge();
getOffice();
}
class Office() {
/**其他信息**/
getTel(); // 办公室电话
getAreaNumbe(); // 办公室电话区号
}
6、内联类
与提炼相反,一个类如果不足以承担一个类的责任,就没有存在的理由,就需要被内联一下。
class Person{
getName();
getAge();
getOffice();
}
class Office() {
getTel();
}
Office由于不具备承担一个类的责任,成员过少。所以内联到调用它的类里比较好,比如这样
class Person{
getName();
getAge();
getOfficeTel();
}