1、开闭原则
对实现的修改关闭,对抽象的扩展开放
有了新功能就为抽象扩展一个新的实现来完成
2、依赖倒转
面向抽象编程,细节依赖于抽象,而不是抽象依赖于细节
接口功能的变更,只需注入一个新的实现即可,依赖于抽象的实现不需要做任何改动
3、里式替换
父类或接口出现的地方,都可由子类替换
父类无法引用子类新增的内容,但可回调子类重写的内容
4、单一职责
一个类只负责一件事,否则类要拆分
往大了说任何需求或功能的变更都不要影响到其他的功能
5、接口隔离
一个接口的粒度应该最小化
一个类在实现接口后不能去实现他根本用不着的方法,否则接口要拆分
6、迪米特法则
最少知道,被依赖者的变化对依赖者的影响越小越好,降低耦合性
7、合成复用:
优先使用对象组合,而不是继承
继承是强耦合,延续了很多不必要的方法,增加子类的体积
1、用于生成对象的方法,实现了创建和使用分离,决定了由谁创建、何时创建
2、工厂模式(简单工厂、工厂方法、抽象工厂)、单例模式、原型模式、建造者模式
一、工厂模式
===用于生产复杂对象
public interface Bean {} // 抽象产品扩展多个具体产品
public class Bean1 implements Bean {}
public class Bean2 implements Bean {}
public class BeanFactory { // 简单工厂:一个具体工厂生产多个具体产品
private Bean bean = null;
public Bean getBean(String beanName) throws Exception {
String className = xmlUtil.getClassName(beanName);
Class c = Class.forName(className);
return (Bean)c.newInstance();
}
}
public interface FatoryBean { // 工厂方法:抽象工厂扩展多个具体工厂,但一个具体工厂只能生产一个具体产品
public Bean getObject();
}
public class FactoryBean1 implements FactoryBean {
public Bean getObject() {
return new Bean1();
}
}
public class FactoryBean2 implements FactoryBean {
public Bean getObject() {
return new Bean2();
}
}
二、单例模式
===不保证一定单例,如反射生成实例
两种模式:加载即创建的饿汉式,用到才创建的懒汉式
饿汉式无法延迟加载,在某些情况下会导致问题,如依赖其他类或配置的加载时,饿汉式会出问题
常见懒汉式实现方式中,new Singleton()可能出现指令重排
实际有三步,1-分配空间、2-创建实体、3-返回空间引用
指令可能重排2、3,若先执行3,则引用不再空,其他线程可直接拿到引用使用
但此时2可能未执行,实际引用的实体还是空
volatile有两个作用:内存屏障与指令重排,二者结合才能实现内存可见
1、读操作
内存屏障指令两个功能:内存屏障,禁止其它指令和我重排
编译器在volatile变量读操作之前插入内存屏障指令,防止读取共享变量的本地内存副本
jvm为了优化性能,可能会将读操作重排序到内存屏障指令之前,但内存屏障指令会禁止重排
2、写操作
编译器在volatile变量写操作之后插入内存屏障,强制刷出本地内存副本的数据到共享内存
// 传统的懒汉式
public class Singleton {
private static Singleton single = null; // 1、改进用volatile修饰
private void singleton() {}
public static Singleton getInstance() {
if(null == single) {
synchronized(Singleton.class) {
if(null == single) {
single = new Singleton();
// 2
Singleton s = new Singleton();
single = s;
}
}
}
return single;
}
}
// 饿汉式改良版的懒汉式
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
三、原型模式
===用于复杂对象,且要求重复创建
对象克隆是复制出一个与原对象内容完全一样的另一个对象
克隆是本地方法,直接在内存中拷贝出一个新对象,其效率比new高很多
如果一个对象特别复杂,当前业务又要求重复创建该对象,为提高创建效率,可以使用克隆
public class ProtoType implements Cloneable {
// 接口没有要实现的方法,就是告诉jvm该类可以使用clone复制对象,否则会抛不支持克隆异常
public int a;
public List list;
public static final ProtoType instance = new ProtoType();
private void ProtoType() {}
public Object clone() { // 重写Object的clone方法,扩展为public
ProtoType p = null;
try {
p = (ProtoType) supper.clone(); // 浅拷贝的话,此处就结束了
// 若有引用成员,必须深拷贝,要先重写引用成员的clone方法
p.list = (List) this.list.clone(); // java的类clone都已经重写了
} catch(CloneNotSupportedException e) { //.. }
}
public ProtoType getInstance() { // 对外以克隆的方式生成实例
return instance.clone();
}
}
四、建造者模式
===用于属性较多的对象
public class CreatPattern {
private int a;
private int b;
...
private void CreatPattern() {}
public class Builder() { // 避开构造方法,利用一个构造器生成想要的实例
CreatPattern c = null;
public void Builder() {
c = new CreatPattern();
}
public Builder setA(int a) {
c.setA(a);
return this;
}
public Builder setB(int b) {
c.setB(b);
return this;
}
...
public CreatPattern build() {
return c;
}
}
...
get/set
}