简介
最近看的书有点杂,看到设计模式部分了,文中介绍的"封装"对我感触很深,花了一天时间研究了一下,方便后面回看,在这里记录一下,回想几年前无脑的getter() setter(),哈哈…
印象比较深的一句话
类或对象作为组织代码的基本单元,并将封装,抽象,继承,多态四个特性,作为代码设计和实现的基石
封装
封装的意义是什么
1.信息隐藏
2.类通过保留有限的访问接口,外部访问仅能通过类提供的方式(或函数)来访问内部信息或者数据
import java.math.BigDecimal;
import java.util.UUID;
public class EncapsulationWallet {
private String id;
private long createTime;
/**
* 钱包余额
*/
private BigDecimal balance;
private long balanceLastModifiedTime;
public EncapsulationWallet(){
this.id= UUID.randomUUID().toString();
this.createTime=System.currentTimeMillis();
this.balance=BigDecimal.ZERO;
this.balanceLastModifiedTime=System.currentTimeMillis();
}
public String getId() { return this.id; }
public long getCreateTime() { return this.createTime; }
public BigDecimal getBalance() { return this.balance; }
public long getBalanceLastModifiedTime() { return this.balanceLastModifiedTime; }
public void increaseBalance(BigDecimal increasedAmount) throws Exception {
if(increasedAmount.compareTo(BigDecimal.ZERO)<0){
throw new Exception("金额不能小于0");
}
this.balance= this.balance.add(increasedAmount);
this.balanceLastModifiedTime=System.currentTimeMillis();
}
public void decreaseBalance(BigDecimal decreasedAmount) throws Exception {
if(decreasedAmount.compareTo(BigDecimal.ZERO)<0){
throw new Exception("金额不能小于0");
}
if(decreasedAmount.compareTo(balance)>0){
throw new Exception("余额不足 insufficient");
}
this.balance=this.balance.subtract(decreasedAmount);
this.balanceLastModifiedTime=System.currentTimeMillis();
}
public static void main(String[] args) throws Exception {
EncapsulationWallet wallet= new EncapsulationWallet();
wallet.increaseBalance(new BigDecimal(100));
/**
* "wallet.increaseBalance(new BigDecimal(0.05));"
* 传入浮点类型:是离散的,计算是不准确的 100.05000000000000000277555756156289135105907917022705078125
*/
wallet.increaseBalance(new BigDecimal("0.05"));
wallet.decreaseBalance(new BigDecimal("0.01"));
System.out.println(wallet.getBalance());
}
}
继承的意义
访问权限控制
1.无需暴露:
id,createTime,balanceLastModifiedTime 都是自动生成的,所以没有必要暴露set方法
2.需要暴露:但缩小暴露的范围
balance
封装带来的好处
1.保护数据(防止外部随意修改)setBalance是可以修改为任意值(-1,-100)等,
但是实际业务角度来说钱包余额,只会有两种修改方式:增或减,缩小数据修改范围,让数据更安全,
2.易用性 时刻保持最小暴露,反而能提高易用性
(如果暴露的是setBalance和setBalanceLastModifiedTime,外部调用者要熟悉业务,更改setBalance时要setBalanceLastModifiedTime)
易用性探讨
电脑开机:
1.比如电脑没有开关按钮,让你手动先启动电源,手动加电CPU,手动加电显卡,手动开机自检,手动加载OS…
2.还是提供一个按钮,一键开机来的实在
抽象
调用方只关注功能点,不用关注功能的具体实现
帮助人类过滤掉一些非关键信息
/**
* 抽象:隐藏方法具体实现
* Java通过Interface 或者 抽象类 来实现
* <p>
* 调用者在使用PictureStorage这个类的功能的时候,只需要了解IPictureStorage 这个提供了哪些功能,并不需要关心里面具体是怎么实现的
* ex:买了一辆车,不用关心车具体是怎么生产出来的怎么跑起来的,只需要用方向盘,油门,刹车就行了(方向盘,油门,刹车就是抽象,接口的功能)
* <p>
* 注意:
* 实际上函数这一语言机制,本身就是一种抽象,我们只管调用不关心内部具体实现,malloc()和free()
* <p>
* 抽象的意义是什么?
* 在面对复杂系统的时候,人脑能承受的信息复杂度是有限的,所以我们必须过滤掉一些非关键性的细节
* 而抽象只关注**功能点**,不关注**具体细节**的设计思路,正好帮我们的大脑过滤掉许多非必要的信息
*/
interface IPictureStorage {
void savePicture();
String getPicture();
void deletePicture();
void modifyMetaInfo(String pictureId, String metaInfo);
}
public class AbstarctionPictureStorage implements IPictureStorage {
@Override
public void savePicture() {
}
@Override
public String getPicture() {
return null;
}
@Override
public void deletePicture() {
}
@Override
public void modifyMetaInfo(String pictureId, String metaInfo) {
}
}
继承
代码复用 :提高代码复用性
/**
* 继承:
*
* 无利不起早,谈好处:代码复用
*
* 两个类有一个相同的属性和方法
* 子类就可以重用父类的代码
* Java 单继承
* is a: XXX 是什么 ,猫是动物
* 区别 interface :XXX 有(能做)什么 ,猫有牙齿
*
* 多用组合 少用继承
*
* 继承的负面影响
* 1:
* 继承层次过深,过于复杂,就会导致代码可读性,可维护性变差,可读性:为了了解一个类,不仅需要查看这个类的代码,还要按照继承关系一层一层往上找
* 2:
* 父类和子类高度耦合,修改父类代码,会直接影响到子类
*
* Java 为什么不支持多继承?
*假设:Dog继承 Animal和 InheritanceAnimal,那么Dog应该继承Animal的方法,还是InheritanceAnimal的方法,调用的时候调用哪个
*
*为什么可以实现(继承)多个interface?
* 因为 interface 只有定义,没有具体的实现
*
*/
class Animal implements hello, world {
public void eat() {
}
@Override
public void print() {
}
}
public class InheritanceAnimal {
public void eat() {
}
}
class Dog extends InheritanceAnimal {
public void fuckEat() {
super.eat();
}
}
interface hello {
void print();
}
interface world {
void print();
}
多态
提供复用性和可扩展性
多态可以动态调用实现了interface的各个子类的方法
package polymophyism.com;
/**
*
*
* 接口是多继承 也可以实现多态
*
* 多态:提高代码的可扩展性和复用性
*
* 假如我有提供了一张纸,那么这张纸就可以拿来写字,不管这个纸是草纸,本子上的纸,墙上的纸)
*
*/
public class InterfaceTest {
private static void print(Iterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
private static void printArray(ArrayBucket arrayIterator) {
while (arrayIterator.hasNext()) {
System.out.println(arrayIterator.next());
}
}
private static void printList(LinkedList linkIterator) {
while (linkIterator.hasNext()) {
System.out.println(linkIterator.next());
}
}
public static void main(String[] args) {
Iterator arrayIterator=new ArrayBucket();
print(arrayIterator);
Iterator listIterator=new LinkedList();
print(listIterator);
}
}
interface Iterator {
boolean hasNext();
String next();
String remove();
}
class ArrayBucket implements Iterator {
@Override
public boolean hasNext() { return true;}
@Override
public String next() {return null;}
@Override
public String remove() {return null;}
}
class LinkedList implements Iterator {
@Override
public boolean hasNext() {return true;}
@Override
public String next() {return null;}
@Override
public String remove() {return null;}
}
实现多态的三个语法机制
1.继承
2.父类对象可以引用子类对象
3.子类能复写父类方法
多态提供可复用性和可扩展性
可扩展性:
假如需要添加一个HashMap,只需要添加一个类 HashMap.java实现Iterator
复用性:
print()接收的参数为Iterator,因此可以动态调用子类的方法
那么就要建立printArray和printList来实现功能
多态是设计模式的基础
多态是很多设计模式、设计原则、编程技巧的基础,比如策略模式,基于接口而非实现编程,依赖倒置,里式替换原则等