.
23种设计模式
创造类
单例模式
懒汉模式
1 2 3 4 5 6 7 8 9 10 |
public class Singleton{ private static Singleton instance = null; private Singleton(){} public static Singleton newInstance(){ if(null == instance){ instance = new Singleton(); } return instance; } } |
饿汉模式
1 2 3 4 5 6 7 |
public class Singleton{ private static Singleton instance = new Singleton(); private Singleton(){} public static Singleton newInstance(){ return instance; } } |
双重检测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Singleton { private static volatile Singleton instance = null; private Singleton(){} public static Singleton getInstance() { if (instance == null) { // Single Checked synchronized (Singleton.class) { if (instance == null) { // Double checked instance = new Singleton(); } } } return instance; } } |
静态内部类
1 2 3 4 5 6 7 8 9 |
public class Singleton{ private static class SingletonHolder{ public static Singleton instance = new Singleton(); } private Singleton(){} public static Singleton newInstance(){ return SingletonHolder.instance; } } |
枚举
1 2 3 4 5 6 7 8 9 10 11 12 |
class Resource{ } public enum SomeThing { INSTANCE; private Resource instance; private SomeThing() { instance = new Resource(); } public Resource getInstance() { return instance; } } |
工厂方法模式
抽象工厂模式
模版方式模式
建造者模式
原型模式
迭代器模式
结构类
代理模式
装饰者模式
适配器模式
组合模式
门面模式
享元模式
桥梁模式
行为类
中介者模式
命令模式
责任链模式
策略模式
观察者模式
备忘录模式
访问者模式
状态模式
解释器模式
6大设计原则
单一职责原则
Single Responsibility Principle,SRP,应该有且只有一个原因引起类的变更。一个方法尽可能做一件事
但是职责和变化原因是不可度量的,因项目而异,因环境而异。建议接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变更。
类的复杂性降低,实现什么职责都有清晰明确的定义。可读性提高,可维护性提高。
里氏替换原则
LiskovSubstitutionPrinciple,LSP,所有引用基类的地方必须能透明地使用其子类的对象。
最佳实践:
- 子类必须完全实现父类的方法
- 子类可以有自己的个性
- 覆盖或实现父类的方法时输入参数可以被放大,子类中方法的输入参数必须与父类中被覆写的方法的输入参数类型相同或者更宽松。
- 覆写或实现父类的方法时输出结果可以被缩小,父类的一个方法返回值是一个类型T,子类的相同方法(重载或覆写)的返回类型为S,要求S类型必须小于等于T类型。
依赖倒置原则
DependenceInversionPrinciple,DIP,模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;接口或抽象类不依赖于实现类;实现类依赖接口或抽象类。
精简的定义就是“面向接口编程”。
-
构造函数传递依赖对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
public interface IDriver{ void drive(); } public class Driver implements IDriver{ private ICar car; // 构造函数注入 public Driver(ICar car){ this.car = car; } @Override public void drive(){ this.car.run(); } }
-
Setter方法传递依赖对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public interface IDriver{ // 接口声明依赖对象 void setCar(ICar car); void drive(); } public class Driver implements IDriver{ private ICar car; // Setter依赖注入 public void setCar(ICar car){ this.car = car; } @Override public void drive(){ this.car.run(); } }
最佳实践:
- 每个类都尽量都有接口或抽象类,或者抽象类或接口两者都具备。
- 变量的表面类型尽量是接口或者抽象类。
- 任何类都不应该从具体类派生。
- 尽量不要覆写基类的方法,如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要覆写。
- 结合里氏替换原则使用。
接口隔离原则
实例接口(Object Interface),在Java中声明一个类,然后用new关键字产生一个实例,它是对一个类型事物的描述,这是一种接口。
类接口(Class Interface),使用interface关键字定义的接口。
两种类型的美女定义:
1 2 3 4 5 6 7 8 |
public interface IGoodBodyGirl{ void goodLooking(); void niceFigure(); } public interface IGreatTemperamentGirl{ void greatTemperament(); } |
最标准的美女:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class PrettyGirl implements IGoodBodyGirl,IGreatTemperamentGirl{ private String name; public PrettyGirl(String name){ this.name = name; } @Override public void goodLooking(){ System.out.println("She has good looking."); } @Override public void niceFigure(){ System.out.println("She has nice figure."); } @Override public greatTemperament(){ System.out.println("She has great temperament."); } } |
最佳实践:
- 一个接口只服务于一个子模块或业务逻辑,通过业务逻辑压缩接口中的public方法,接口时长去回顾,尽量让接口达到“满身筋骨肉”,而不是“肥嘟嘟”的一大堆方法。
- 已经被污染的接口,尽量去修改,若变更的风险较大,则采用适配器模式去转化处理。
迪米特法则
LawofDemeter,LoD,一个类应该对自己需要耦合或调用的类知道的最少,你的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的那么多public方法,我就调用这么多,其他我一概不管。
核心概念就是类间解藕,弱耦合,只有弱耦合了以后,类的复用率才可以提高。
开闭原则
类、模块和函数应该对扩展开放,对修改关闭。