目录

前言

一、设计原则

1.1 开闭原则

1.2 单一职责原则

1.3 依赖倒置原则

1.4 接口分离原则

1.5 迪米特法则

1.6 里氏替换原则

二、设计模式

2.1 单例模式

2.1.1 饿汉式

2.1.2 懒汉式非安全

2.1.3 懒汉式安全

2.1.4 double+check

2.1.5 静态内部类

2.1.6 枚举

2.2 建造者模式

2.3 适配器模式

2.4 桥接模式

2.5 装饰器模式

2.6 责任链模式

2.7 模板模式

总结


前言

合理的使用设计模式可以简化开发,提高代码的阅读量,让代码看起来更加的精简,代码结构层次更加的清晰,学习设计模式可以让我们的思维更加的灵活和抽象化。

代码中从不使用设计模式的缺点是:代码看起来繁杂、凌乱、臃肿和代码占用大小增加,阅读性差,找不到阅读入口等等。

但是如果不熟悉设计模式,没有深入的研究过,不了解它的核心思想,生搬硬套的使用设计模式,也会出现线程安全,资源泄露和代码性能降低等等问题。

这篇文章就是以我的理解对常用的设计模式进行讲解,帮助读者快速的了解这些设计模式,但是怎么使用它,还是要看具体的场景。


一、设计原则

简单的介绍一下六大设计原则,因为设计模式离不开这些原则。

1.1 开闭原则

 对外扩展开发,对内修改关闭。

如:一个人单身男每天必须要吃早餐,而且就两样鸡蛋和牛奶,其他啥也不吃。

public class Person {public void eatBreakFast(){System.out.println("吃鸡蛋");System.out.println("喝牛奶");}}

假如有一天他找到女朋友了,女朋友说:你必须要吃面包。(女朋友的话必须听,不能反驳)

这个时候在不满足开闭原则的话,是下面的样子。

public class Person {public void eatBreakFast(){System.out.println("吃鸡蛋");System.out.println("喝牛奶");System.out.println("吃面包");}}

那么满足开闭原则的话是这样的。

public class Person {public void eatBreakFast(){System.out.println("吃鸡蛋");System.out.println("喝牛奶");}public void eatBreakFastOfHasGirlFriend(){System.out.println("吃鸡蛋");System.out.println("喝牛奶");System.out.println("吃面包");}}

这样一来,我们不改变之前的逻辑和功能,只对它进行扩展。调用者只需要调用新的方法就行了。 这样有一天调用者想调用之前的方法,只需要换个方法名就行了。(如果那一天他失恋了,没有女朋友了,他还可以按照之前的方式吃早餐。。。。。他应该很开心吧。。。。。。)

1.2 单一职责原则

 一个类、接口或者方法只允许有一个职责。

用方法来说明,假设一个方法就是一个人。

如果不满足单一职责原则,是这样的。

public class Person {public void person(){System.out.println("我是一名电工,会修电,我有相关证书");System.out.println("我是一名厨师,会做饭,我有相关证书");System.out.println("我是一名教师,会教书,我有相关证书");System.out.println("我是一名医生,会看病,我有相关证书");}}

我们为了不让这个方法(人)臃肿(累死),所以单一职责原则出现了。

public class Person {public void person1(){System.out.println("我是一名电工,会修电,我有相关证书");}public void person2(){System.out.println("我是一名厨师,会做饭,我有相关证书");}public void person3(){System.out.println("我是一名教师,会教书,我有相关证书");}public void person4(){System.out.println("我是一名医生,会看病,我有相关证书");}}

单一职责的原理就是,为了在有一天要变更某一个功能时,变动的地方更小,只涉及某一个功能。(假设这个人很厉害,辛辛苦苦到80岁,终于所有证书都有了,都可以合法做这些事挣钱养家了,某一天接到通知,所有的证书要重新考试,问:此时他的心理阴影面。。。。。。。。)

1.3 依赖倒置原则

依赖抽象而不是依赖实现。抽象不应该依赖细节,细节应该依赖抽象。高层模块不能依赖低层模块,二者都应该依赖抽象。

假如不满足依赖倒置原则,喜羊羊吃草是这样的。

// 小草
public interface Grass {void grassType();
}
// 红颜色的小草
public class RedGrass implements Grass{@Overridepublic void grassType() {System.out.println("我是红颜色的小草,来吃我吧");}
}
// 绿颜色的小草
public class GreenGrass implements Grass{@Overridepublic void grassType() {System.out.println("我是绿颜色的小草,来吃我吧");}
}// 测试代码
public class Test {// 红色的草static RedGrass redGrass;public Test(RedGrass redGrass) {this.redGrass = redGrass;}public static void main(String[] args) {new Test(new RedGrass());System.out.println("我是喜羊羊,我要吃草");redGrass.grassType();}}

假如有一天,这个世界上没有红色的草,那么喜羊羊就没了。。。。。,满足依赖倒置原则时,是这样的。

public class Test {// 是草就行static Grass grass;public Test(Grass grass) {this.grass = grass;}public static void main(String[] args) {new Test(new RedGrass());System.out.println("我是喜羊羊,我要吃草");grass.grassType();new Test(new GreenGrass());System.out.println("我是喜羊羊,我要吃草");grass.grassType();}}

这样一来,不知道你们有没有明白依赖倒置原则的思想,反正喜羊羊是不会饿死的,是个草它就可以吃。。。。。。。。

1.4 接口分离原则

采用多个与特定客户类有关的接口比采用一个通用的接口要好。

假如一个有女朋友的人,他女朋友一星期,每一天要穿不同的衣服,这些衣服都要他提前准备好。不满足接口分离原则的时候是这样。

public class Boy implements Clothes{public void getClothes(String date){if (date.equals("星期一")){System.out.println("今天你穿:牛仔裤搭配高跟鞋");} else if (date.equals("星期二")){System.out.println("今天你穿:牛仔裤搭配运动鞋");}else if (date.equals("星期三")){System.out.println("今天你穿:牛仔裤搭配帆布鞋");}else if (date.equals("星期四")){System.out.println("今天你穿:裙子搭配高跟鞋");}else if (date.equals("星期五")){System.out.println("今天你穿:裙子搭配运动鞋");}else if (date.equals("星期六")){System.out.println("今天你穿:裙子搭配帆布鞋");}else if (date.equals("星期七")){System.out.println("今天你穿:九分裤搭配运动鞋");}}
}

使用接口分离原则是这样的。

public class Boy implements Clothes{@Overridepublic void getMondayClothes(String date) {System.out.println("今天你穿:牛仔裤搭配高跟鞋");}@Overridepublic void getTuesdayClothes(String date) {System.out.println("今天你穿:牛仔裤搭配运动鞋");}@Overridepublic void getWednesdayClothes(String date) {System.out.println("今天你穿:牛仔裤搭配帆布鞋");}@Overridepublic void getThuresdayClothes(String date) {System.out.println("今天你穿:裙子搭配高跟鞋");}@Overridepublic void getFridayClothes(String date) {System.out.println("今天你穿:裙子搭配运动鞋");}@Overridepublic void getSaturdayClothes(String date) {System.out.println("今天你穿:裙子搭配帆布鞋");}@Overridepublic void getSundayClothes(String date) {System.out.println("今天你穿:九分裤搭配运动鞋");}
}

1.5 迪米特法则

一个类对于其他类知道的越少越好。一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。

public class Wolf {public static String name = "灰太狼";
}public class Test {private String name = "喜羊羊";public static void main(String[] args) {System.out.println("我是" + name + ",小灰灰的爸爸是:" + Wolf.name);}}

不满足迪米特法则,那么喜羊羊就可以知道小灰灰的爸爸是谁,灰太狼不想让它的名字被别的羊知道,就要用满足迪米特法则。

public class Wolf {private static String name = "灰太狼";
}public class Test {private String name = "喜羊羊";public static void main(String[] args) {//得不到Wolf.nameSystem.out.println("我是" + name + ",小灰灰的爸爸是:" + Wolf.name);}}

1.6 里氏替换原则

派生类(子类)对象可以在程式中代替其基类(超类)对象,但是不能重写父类的非抽象方法。

这个就是多态的使用,不用讲解了。


二、设计模式

2.1 单例模式

属于创建型模式,它提供了一种创建对象的最佳方式。满足以下三点:

单例类只能有一个实例。

单例类必须自己创建自己的唯一实例。

单例类必须给所有其他对象提供这一实例。

2.1.1 饿汉式

public class Singleton {private Singleton() {}private static Singleton singleton= new Singleton();public static Singleton getSingleton(){return singleton;}}

2.1.2 懒汉式非安全

public class Singleton {private static Singleton singleton;private Singleton (){}public static Singleton getInstance() {// 多线程并发到这时,不能保证单例,所以不安全if (singleton == null) {singleton = new Singleton();}return singleton;}}

2.1.3 懒汉式安全

public class Singleton {private static Singleton singleton;private Singleton (){}// 安全是安全了,可以高并发都在这阻塞的话,降低性能public static synchronized Singleton getInstance() {if (singleton == null) {singleton = new Singleton();}return singleton;}}

2.1.4 double+check

public class Singleton {private volatile static Singleton singleton;private Singleton (){}public static Singleton getSingleton() {// 为空时才抢锁创建if (singleton == null) {// 加锁synchronized (Singleton.class) {// 再次判断,如果抢到锁发现已经不为空,证明之前抢到锁的已经创建了if (singleton == null) {// 没有的话就创建一个singleton = new Singleton();}}}// 直接返回return singleton;}}

2.1.5 静态内部类

public class Singleton {private static class SingletonHolder {private static final Singleton SINGLETON = new Singleton();}private Singleton (){}public static final Singleton getInstance() {return SingletonHolder.SINGLETON;}}

2.1.6 枚举

public enum Singleton {SINGLETON;public void doooooo() {//.........}}public class Test {public static void main(String[] args) {Singleton.SINGLETON.doooooo();}}

根据使用什么类型的单例,还是要结合业务和实际的需要。

2.2 建造者模式

使用多个简单的对象一步一步构建成一个复杂的对象。属于创建型模式

//阳台
public class Balcony {
}
// 客厅
public class DrawingRoom {
}
// 书房
public class Study {
}
// 卫生间
public class Toilet {
}// 构建一个房子,按照不同人的爱好
public class Room {// 阳台private Balcony balcony;// 客厅private DrawingRoom drawingRoom;// 书房private Study study;// 卫生间private Toilet Toilet;public Room(RoomFactory.Builder builder) {this.balcony = builder.balcony;this.drawingRoom = builder.drawingRoom;this.study = builder.study;this.Toilet = builder.Toilet;}}
public class RoomFactory {private RoomFactory() {}// 内部的工具类public static class Builder{// 阳台public Balcony balcony;// 客厅public DrawingRoom drawingRoom;// 书房public Study study;// 卫生间public Toilet Toilet;public Builder builderBalcony(Balcony balcony) {this.balcony = balcony;return this;}public Builder builderDrawingRoom(DrawingRoom drawingRoom) {this.drawingRoom = drawingRoom;return this;}public Builder builderStudy(Study study) {this.study = study;return this;}public Builder builderToilet(builder.Toilet toilet) {Toilet = toilet;return this;}// 构建房子public Room build(){return new Room(this);}private Builder() {}}// 对外入口public static RoomFactory.Builder builder(){return new Builder();}}

构建两个不同设计的房子

public class Test {public static void main(String[] args) {Balcony balcony = new Balcony();DrawingRoom drawingRoom = new DrawingRoom();Study study = new Study();Toilet toilet = new Toilet();Room room1= RoomFactory.builder().builderBalcony(balcony).builderStudy(study).build();Room room2= RoomFactory.builder().builderToilet(toilet).builderDrawingRoom(drawingRoom).build();}}

2.3 适配器模式

两个不兼容的接口之间的桥梁。属于结构型模式

假设现在的播放器只支持MP4格式,不支持其他格式。

public interface Video {void play(String format);}public class CommonVideo implements Video{@Overridepublic void play(String format) {if (format.equals("MP4")){System.out.println("播放MP4格式视频");}else {System.out.println("不支持的播放格式");}}
}

如果我们要进行升级,让它支持更多的格式,可以使用适配器模式。

// 定义高级视频播放器
public interface AdvancedVideo {void playAVI();void playWMV();void playRM();}public class AVIAdvancedVideo implements AdvancedVideo{@Overridepublic void playAVI() {System.out.println("播放AVI格式视频");}@Overridepublic void playWMV() {}@Overridepublic void playRM() {}
}public class WMVAdvancedVideo implements AdvancedVideo{@Overridepublic void playAVI() {}@Overridepublic void playWMV() {System.out.println("播放WMV格式视频");}@Overridepublic void playRM() {}
}public class RMAdvancedVideo implements AdvancedVideo{@Overridepublic void playAVI() {}@Overridepublic void playWMV() {}@Overridepublic void playRM() {System.out.println("播放RM格式视频");}
}// 定义适配器
public class VideoAdapter implements Video{private AdvancedVideo advancedVideo;public VideoAdapter(String format) {if (format.equals("AVI")){this.advancedVideo = new AVIAdvancedVideo();}else if (format.equals("WMV")){this.advancedVideo = new WMVAdvancedVideo();}else if (format.equals("RM")){this.advancedVideo = new RMAdvancedVideo();}else {// 按照业务进行不同处理}}@Overridepublic void play(String format) {if (format.equals("AVI")){advancedVideo.playAVI();}else if (format.equals("WMV")){advancedVideo.playWMV();}else if (format.equals("RM")){advancedVideo.playRM();}else {// 按照业务进行不同处理}}
}// 基础播放器支持其他格式
public class CommonVideo implements Video{@Overridepublic void play(String format) {if (format.equals("MP4")){System.out.println("播放MP4格式视频");}else if (format.equals("AVI") || format.equals("WMV") || format.equals("RM")){new VideoAdapter(format).play(format);}else {System.out.println("不支持的播放格式");}}public static void main(String[] args) {CommonVideo commonVideo = new CommonVideo();commonVideo.play("MP4");commonVideo.play("AVI");commonVideo.play("WMV");commonVideo.play("RM");}
}

它的缺点也很明显,如果新增播放格式,要修改很多类。

2.4 桥接模式

抽象化与实现化解耦,使得二者可以独立变化。属于结构型模式

public interface Person {void doSomething();
}public class Programmer implements Person{@Overridepublic void doSomething() {System.out.println("我是程序员,我会写代码");}
}public class Accountant implements Person {@Overridepublic void doSomething() {System.out.println("我是会计,我会统计财务消息");}
}// 对外的对象,提供调用者
public abstract class Worker {protected Person person;public Worker(BridgePattern.Person per) {this.person = per;}public abstract void doSome();}// 桥接对象
public class PersonBridge extends Worker{public PersonBridge(BridgePattern.Person per) {super(per);}@Overridepublic void doSome() {person.doSomething();}}public class Test {public static void main(String[] args) {// PersonBridge只依赖抽象的Person,不管实现者是谁Worker accountant = new PersonBridge(new Accountant());accountant.doSome();Worker programmer = new PersonBridge(new Programmer());programmer.doSome();}
}

2.5 装饰器模式

允许向一个现有的对象添加新的功能,同时又不改变其结构。属于结构型模式

对一个普通的火锅进行不同的装饰。

// 火锅
public interface HotPot {void dooo();}public class BaseHotPot implements HotPot{@Overridepublic void dooo() {System.out.println("来个底料");}
}public class Lettuce implements HotPot {private HotPot hotPot;public Lettuce(HotPot hotPot) {this.hotPot = hotPot;}@Overridepublic void dooo() {hotPot.dooo();System.out.println("要一斤生菜");}
}public class Onion implements HotPot {private HotPot hotPot;public Onion(HotPot hotPot) {this.hotPot = hotPot;}@Overridepublic void dooo() {hotPot.dooo();System.out.println("要一斤洋葱");}
}public class Garlic implements HotPot {private HotPot hotPot;public Garlic(HotPot hotPot) {this.hotPot = hotPot;}@Overridepublic void dooo() {hotPot.dooo();System.out.println("要一斤蒜");}
}
public class Test {public static void main(String[] args) {// 只要火锅底料HotPot baseHotPot = new BaseHotPot();baseHotPot.dooo();System.out.println();// 要火锅底料+蒜HotPot garlic = new Garlic(baseHotPot);garlic.dooo();System.out.println();// 要火锅底料+蒜+生菜HotPot lettuce = new Lettuce(garlic);lettuce.dooo();System.out.println();// 要火锅底料+生菜+洋葱HotPot lettuce1 = new Lettuce(baseHotPot);HotPot onion = new Onion(lettuce1);onion.dooo();}}// 输出
来个底料来个底料
要一斤蒜来个底料
要一斤蒜
要一斤生菜来个底料
要一斤生菜
要一斤洋葱

2.6 责任链模式

为请求创建了一个接收者对象的链。 属于行为型模式

public interface Teacher {void correct(String job);}public class MathTeacher implements Teacher{@Overridepublic void correct(String job) {if (job.contains("数学作业")){System.out.println("我是数学老师,批改数学作业");}}
}public class ChineseTeacher implements Teacher{@Overridepublic void correct(String job) {if (job.contains("语文作业")){System.out.println("我是语文老师,批改语文作业");}}
}public class PhysicsTeacher implements Teacher{@Overridepublic void correct(String job) {if (job.contains("物理作业")){System.out.println("我是物理老师,批改物理作业");}}
}public class HistoryTeacher implements Teacher{@Overridepublic void correct(String job) {if (job.contains("历史作业")){System.out.println("我是历史老师,批改历史作业");}}
}
public class TeacherChain {private static ArrayList<Teacher> teachers;static {teachers = new ArrayList<>();teachers.add(new HistoryTeacher());teachers.add(new MathTeacher());teachers.add(new ChineseTeacher());teachers.add(new PhysicsTeacher());}public static void correctJob(String job){for (Teacher teacher : teachers){teacher.correct(job);}}
}public class Test {public static void main(String[] args) {TeacherChain.correctJob("数学作业|语文作业");System.out.println();TeacherChain.correctJob("数学作业|历史作业|物理作业");}}我是数学老师,批改数学作业
我是语文老师,批改语文作业我是历史老师,批改历史作业
我是数学老师,批改数学作业
我是物理老师,批改物理作业

2.7 模板模式

一个抽象类公开定义了执行它的方法的方式/模板。属于行为型模式

public abstract class Person {// 模板方法protected void eat(){System.out.println("吃饭");}protected abstract void doooo();}public class Teacher extends Person {@Overrideprotected void doooo() {System.out.println("上课");}
}public class Student extends Person {@Overrideprotected void doooo() {System.out.println("学习");}
}public class Test {public static void main(String[] args) {Student student = new Student();student.eat(); // 公共的行为,可以共享,提供一个模板student.doooo();Teacher teacher = new Teacher();teacher.eat(); // 公共的行为,可以共享,提供一个模板teacher.doooo();}
}

提供一个模板,可以共用。


总结

一起进步,一起写出更优秀的代码。

【Java 常用的设计模式】相关推荐

  1. Java常用的设计模式总结

    前言 java设计模式有23种,他们分别是: 创建型模式:单例模式.抽象工厂模式.建造者模式.工厂模式.原型模式. 结构型模式:适配器模式.桥接模式.装饰器模式.组合模式.外观模式.享元模式.代理模式 ...

  2. java 常用十种设计模式示例归纳 | 已打包请带走

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. GitHub地址 DesignPattern 文章说明 一个Demo,集合常用的十种设计模 ...

  3. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

  4. JAVA常用设计模式(一、单例模式、工厂模式)

    JAVA设计模式之单例模式 import java.util.HashMap; import java.util.Map;/*** 设计模式之单例模式* 单例模式(Singleton Pattern) ...

  5. Java常用设计模式————原型模式(一)

    介绍 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 原型模式用于创建重复的对象,同时又能保证性能.当直接创建对象的代价比较大时,则采用 ...

  6. Java常用设计模式————工厂模式

    简介: 工厂模式(Factory Pattern)是Java中最常用的设计模式之一,又称多态工厂模式.虚拟构造器模式.属于创建型模式. 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通 ...

  7. Java开发中常用的设计模式-单例模式

    单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式. Java开发中常用的设计模式-单例模式 单例模式有3个特点: 单例类只有一个实例对象: 该单例对象必须 ...

  8. 初学Java常用设计模式之——原型模式

    声明:转载请附上原文链接 提示:标题序号从3开始,是照应不同设计模式笔记发布的顺序而定的,比如,第上一篇文章 初学Java常用设计模式之--工厂模式 序号从2开始. 标题后面之所以加上了解,是因为相对 ...

  9. java常用设计模式文章收集

    java常用设计模式文章收集 java设计模式--接口模式 java设计模式--抽象工厂模式 java设计模式--工厂模式 Java设计模式--迭代器模式 Java设计模式--原型模式 JAVA设计模 ...

最新文章

  1. 对 Thinking in java 4th Edition I/O DirList.java的疑问
  2. CTFshow 文件上传 web154
  3. Centos安装Xen总结
  4. 关于return的用法
  5. 孩子哭的时候大人应该怎么办?
  6. matlab考试,MATLAB考试题
  7. yarn在vscode里启动报错
  8. MFC基础教程之窗口定义(一)
  9. centos6 与 7 其中的一些区别
  10. php invoke 反射,PHP ReflectionMethod invoke()用法及代码示例
  11. vue 为全局变量赋值_在vue项目中 如何定义全局变量 全局函数
  12. Mapper代理详解,Mapper代理的作用以及用法,结合之前写的mybatis框架讲解、mapper代理的好处
  13. 【C语言学习教程---1】VC++6.0的安装和创建简单C语言工程文件教程
  14. 【0514 更新中】CVPR 2019 论文汇总 按方向划分
  15. 在 Mac/win7 下上使用 Vagrant 打造本地开发环境
  16. linux sssd服务启动失败,active-directory – SSSD Kerberos AD Centos故障排除
  17. 熬夜加班问题总结反思
  18. 如何有效学习《恋上数据结构与算法》,更快地理解数据代码?
  19. DisplayInfo
  20. 【转录调控网络】典型的基因转录调控网络推导方法——布尔网络

热门文章

  1. Set 集合以及Set集合的一些常用方法
  2. c#连接sqlserver数据库-百分百能连接成功的代码超详细
  3. JavaScript异步与同步解析
  4. Google.cn刚上不去了
  5. SwipeRefreshLayout极其简单的下拉刷新工具
  6. python3.8安装mayavi4.7.3
  7. Windows 任务计划程序
  8. linux内核中锁有哪些,Linux内核中有哪些锁
  9. jacob操作API
  10. [opencv][cpp] 学习手册3:多边形拟合