S 是 F 的子类,如果 S 的编译类型是 F,那么 S 的行为尽量和 F 保持一致。意思就是子类尽量不要覆盖父类的方法。
override:推翻、覆盖。
之所以被翻译成“重写”,我认为是 override 看起来或者听起来有点像 overwrite,而它确实有“覆盖,重写”的意思,但并不是关键字,而且“重写”听起来不如“覆盖”那么那么容易理解。
迪米特法则
也叫最少知道原则。一个类尽量与自已有直接依赖关系的类或接口产生联系。
比如 controller 中只与 service 层产生直接联系,没有 dao 层的依赖;
明星与经纪人是直接联系,经纪人和粉丝直接联系。
接口隔离原则
不要试图创建一个很庞大的接口,而应该针对特定的功能去设计接口。比如 person 接口有 eat,study,work,sleep 四个方法,那么 Teacher 类和 Student 类实现这个接口的时候,都必须实现这四个方法,但是 Teacher 无需实现 study 方法,Student 类也无需实现 work 方法,这就造成代码冗余了。
更好的方法应该是,创建三个接口:Person,Teacher,Student,Person 只有 eat,sleep 方法,Student 接口只有 study 方法,Teacher 类只有 work 方法。
那么,老师类实现 Person、Teacher 这两个接口,学生类实现 Person、Student 这两个接口。
依赖倒置原则
高层模块尽量依赖抽象,而不是具体的实现类。比如 controller 类应该依赖的是 Service 接口,而不是 Service 实现类。
有什么好处呢?
如果要替换 Service 实现类,那么就只需要替换实现类,而Service,controller 是不用变的。
创建型
单例模式
饿汉式
1. 构造器私有化2. 创建静态对象3. 提供外部统一访问方法
package singleton.case1;
/**
* 单例模式:饿汉式
*/
public class Singleton1 {
/**
* 必须是静态的,如果不是静态的,那么 getInstance 方法就无法使用这个变量名
* 静态方法只能使用静态成员。
* 因为非静态成员是属于对象的,但是调用非静态成员必须创建对象。
*/
private static Singleton1 instance = new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance() {
return instance;
}
}
复制代码
为什么 getInstance 方法是静态的?
因为如果是非静态的,那么必须创建对象,来调用这个方法,但是构造器是不能被外部调用的。
为什么 instance 是静态的?
如果不是静态的,那么 getInstance 方法就无法使用这个变量名。
为什么静态方法只能使用静态成员?
静态方法不属于对象,属于类,因此调用静态方法的时候,是类在调用。方法体中,返回一个对象,返回的是方法调用者的对象,也就是类对象,所以 instance 是静态的。
如果是非静态方法,那么就是对象在调用,方法体中,返回的对象,是属于对象的。对象的成员可以是静态的,也可以是非静态的。
非静态方法返回的对象,默认是属于 this 的,this 表示当前方法的调用者(实例对象)。这也就是为什么静态方法不能出现 this 的原因。
总结:
方法体中出现 this,this 表示当前方法的调用者,调用者是实例对象;
静态方法的调用者是类本身,因此静态方法中不可能出现 this。也不可能出现非静态成员,因为非静态成员是和实例对象相关联的。
工厂模式
一个方法,一个参数,就能创建指定的产品看到XXXFactory形式的类,就要想到这是一个工厂类,它使用了工厂模式,例如 Spring 的BeanFactory、Mybatis 的 SqlSessionFactory。
简单工厂模式
工厂直接创建产品
package com.cskaoyan.fatory.simple;
import com.cskaoyan.fatory.bean.Animal;
import com.cskaoyan.fatory.bean.Pig;
import com.cskaoyan.fatory.bean.Rabbit;
/**
* 简单工厂
*/
public class SimpleAnimalFactory {
/**
* 提供一个方法,根据不同的参数,获取不同的对象实例
* @param animalName
* @return
*/
public static Animal getAnimal(String animalName) {