java常用设计模式总结
设计模式了解
什么是设计模式?
设计模式(Design pattern)是一套被反复使用的代码设计经验的总结。
为什么使用设计模式
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性以及代码的结构更加清晰.
设计模式的7大原则
1、单一职责原则
一个类只负责一项职责。
2、接口隔离原则
一个类对另一个类的依赖应该建立在最小接口上。

3、依赖倒转原则
①高层模块不应该依赖底层模块,二者都应该依赖其抽象
②抽象不应该依赖细节(实现类),细节应该依赖抽象
③依赖倒置的中心思想是面向接口编程,使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
依赖传递的方式:
接口传递
构造方法传递
setter方法传递
[ ] 详细说明
4、里氏代换原则(Liskov Substitution Principle)
子类中尽量不要重写父类的方法。如果重写,可以将父类中要重写的方法提取到新的类,两个类同时继承新的类,这样做可以降低耦合性。
5、开闭原则(Open Close Principle)
在程序需要进行拓展的时候,不能去修改原有的代码,实现一个优化的效果。对扩展开放,对修改关闭。
6、迪米特法则(最少知道原则)(Demeter Principle)
一个类对自己依赖的类知道的越少越好。被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供public方法之外,不对外泄露任何信息。
7.合成复用原则
原则是尽量使用合成/聚合的方式,而不是使用继承。
设计模式分类
有23种,三大类设计模式。
创建型模式(用于解耦对象的实例化过程): (5种)
单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
行为型模式(对象的功能): (7种) 把。
适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
结构型模式(对象的组成): (11种)
模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。
设计模式详细介绍
创建型
1、单例模式
这个类只能有一个实例,提供全局访问
私有构造方法,私有静态对象,提供公有静态getInstance()方法获取实例。
饿汉:不管需不需要都先创建好(浪费空间)
静态常量
public class Student {
private Student() {}
private static Student s = new Student();
public static Student getInstance() {
return s;
}
}
静态代码块
public class Student{
private Student(){};
private statice Student s;
static{
s=new Student();
}
public static Student getInstance() {
return s;
}
}
懒汉:需要的时候再创建实例
线程不安全
public class Student {
private Student() {}
private static Student s =null ;
public static Student getInstance() {
if(s==null) {
s = new Student();
}
return s;
}
}
同步方法(不管是否实例化都加锁,会影响效率)
public class Student {
private Student() {}
private static Student s =null ;
public static synchronized Student getInstance() {
if(s==null) {
s = new Student();
}
return s;
}
}
同步代码块(不能绝对单例,多线程进入if判断则有问题)
public class Student {
private Student() {}
private static Student s =null ;
public static Student getInstance() {
if(s==null) {
synchronized(Student.class){
s = new Student();
}
}
return s;
}
}
双重检查(DCL) 再加一个if判断
public class Student {
private Student() {}
private static Student s =null ;
public static Student getInstance() {
if(s==null) {
synchronized(Student.class){
if(s==null) {
s = new Student();
}
}
}
return s;
}
}
JDK < 1.5 的时候不可用,由于volatile关键字会屏蔽Java虚拟机
所做的一些代码优化,可能会导致系统运行效率降低,
而JDK 1.5 以及之后的版本都修复了这个问题。
静态内部类,最推荐!
在Student类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载静态内部类,从而完成Student的实例化。 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
public class Student {
private Student() {}
private static class InnerStudent{
private static final Student s = new Student();
}
public static Student getInstance() {
return InnerStudent.s;
}
}
枚举
不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
public enum Student{
STUDENT;
}
总结:
2、工厂模式:
一个工厂类根据传入的参量决定创建出哪一种产品类的实例。
简单工厂(静态工厂)
把创建对象的事情交给工厂来做。
缺点:有新的对象的时候要不断的修改工厂类,不利于后期的维护。
1.创建一个工厂类。
public class Factory {
/*
* 获取对象的静态方法
*/
public static Object getInstance(String objectName) {
if("person".equals(objectName)) {
return new Person();
}else if("student".equals(objectName)) {
return new Student();
}
return null;
}
}
2.创建运行类main方法
public class Case1 {
public static void main(String[] args) {
// 获取一个对象 - 工厂模式 (创建对象)
Object instance = Factory.getInstance("person");
Factory.getInstance("student");
}
}
3、抽象工厂模式:
创建相关或依赖对象的家族,而无需明确指定具体类。
4、建造者模式:
封装一个复杂对象的创建过程,并可以按步骤构造。
5、原型模式:
通过复制现有的实例来创建新的实例。
结构型
1、装饰模式:
动态的给对象添加新的功能。
比如房子装修,那房子还是那个房子,只是在房子墙壁上做粉刷,贴墙纸,挂饰品等。java里面的io流,我们经常如下使用
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
1.创建一个电话接口
public interface PhoneOpration {
/*打电话*/
void call();
}
2.创建电话类实现电话接口
public class Phone implements PhoneOpration{
@Override
public void call() {
System.out.println("通话。。。");
}
}
3.创建一个电话装饰类实现电话接口
/*手机被装饰类*/
public class PhoneDecorate implements PhoneOpration{
/*手机对象引用*/
private PhoneOpration phone;
public PhoneDecorate(PhoneOpration phone) {
super();
this.phone = phone;
}
@Override
public void call() {
phone.call();
}
}
4.创建音乐手机继承手机装饰类,就可以打电话之前听音乐
public class MusicPhone extends PhoneDecorate{
public MusicPhone(PhoneOpration phone) {
super(phone);
}
@Override
public void call() {
music();
super.call();
}
public void music() {
System.out.println("听歌曲");
}
}
4.创建电影手机,就可以打电话之后看电影
public class MoviePhone extends PhoneDecorate{
public MoviePhone(PhoneOpration phone) {
super(phone);
}
@Override
public void call() {
super.call();
movie();
}
public void movie() {
System.out.println("看电影");
}
}
创建测试类
public class TestPhone {
public static void main(String[] args) {
/*构建手机*/
PhoneOpration op = new Phone();
PhoneOpration opx = new PhoneDecorate(op);
opx.call();/*打电话*/
System.out.println("----------------------");
PhoneOpration opz = new MusicPhone(opx);
opz.call();/*听歌,打电话*/
System.out.println("---------------------");
PhoneOpration m = new MoviePhone(opz);
m.call();/*听歌,打电话,看电影*/
}
}
2、代理模式:
为其它对象提供一个代理以便控制这个对象的访问。
静态代理
动态代理
jdk动态代理
cglib动态代理
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
适配器模式:将一个类的方法接口转换成客户希望的另一个接口。
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
享元模式:通过共享技术来有效的支持大量细粒度的对象。
行为型
模板模式:
定义一个算法结构,而将一些步骤延迟到子类实现。
定义一个模板类
public abstract class Template {
/*实现任意业务逻辑*/
public abstract void a();
/*模板方法:计算任意方法运行花费的时间*/
public void getTime() {
long start = System.currentTimeMillis();
a();
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-start)/1000+"s");
}
}
子类继承模板类,并将具体方法延迟到子类
public class Case3 extends Template{
@Override
public void a() {
for(int i=0;i<10;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i="+i);
}
}
public static void main(String[] args) {
Case3 case3 = new Case3();
//计算for循环耗时
case3.getTime();
}
}
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
观察者模式:对象间的一对多的依赖关系。
仲裁者模式:用一个中介对象来封装一系列的对象交互。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
访问者模式:不改变数据结构的前提下,增加作用于一组对象元素的新功能。