设计模式六大原则

1.开放封闭原则:对扩展开放,对修改封闭,意即程序拓展时不要动原有的代码

2.LSP原则:任何基类可以出现的地方,子类一定可以出现

3.依赖倒置原则:使用接口,依赖于抽象而不是具体

4.接口隔离原则:为了解耦,使用多个相互隔离的接口

5.迪米特法则:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

6.CRP法则:尽量使用合成/聚合的方式,而不是使用继承。

分类

1.创建型模式(在创建对象的过程中尽量隐藏创建细节,不直接使用new)

  • 工厂模式(Factory Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)
  • 单例模式(Singleton Pattern)
  • 建造者模式(Builder Pattern)
  • 原型模式(Prototype Pattern)

2.结构型模式(主要关注类和对象的继承、组合)

  • 适配器模式(Adapter Pattern)
  • 桥接模式(Bridge Pattern)
  • 过滤器模式(Filter、Criteria Pattern)
  • 组合模式(Composite Pattern)
  • 装饰器模式(Decorator Pattern)
  • 外观模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)
  • 代理模式(Proxy Pattern)

3.行为型模式(关注对象之间的通信)

  • 责任链模式(Chain of Responsibility Pattern)
  • 命令模式(Command Pattern)
  • 解释器模式(Interpreter Pattern)
  • 迭代器模式(Iterator Pattern)
  • 中介者模式(Mediator Pattern)
  • 备忘录模式(Memento Pattern)
  • 观察者模式(Observer Pattern)
  • 状态模式(State Pattern)
  • 空对象模式(Null Object Pattern)
  • 策略模式(Strategy Pattern)
  • 模板模式(Template Pattern)
  • 访问者模式(Visitor Pattern)

工厂模式

现在要创建一些对象,他们都实现了某个接口或者继承了某个类。我们不在需要的时候使用new操作符,而是把创建的操作让一个“工厂类”完成,我们在需要新对象时只需要把需要的东西的名字以参数形式传递给工厂类就行了,而不用去管怎么创建的。

抽象工厂模式

在工厂模式中,一个工厂类只生产实现某个接口或者继承了某个类的对象,也就是具体工厂生产具体对象,如果建立一个抽象工厂类和若干个具体工厂,每个具体工厂负责产生一类对象,就成了抽象工厂模式。就是一个抽象工厂类可以生产多种类型的对象,具体每种类型的对象怎么生成,要用一个专门的工厂类来决定。

单例模式

一个类,他虽然有构造方法,但是把它设定为private,不能被外界使用。这个类只存在一个实例,保存在这个类自己的一个静态字段里,如果要用这个类的实例属性、实例方法,都通过这个静态字段访问这个唯一的实例来实现。

建造者模式

现在要创建一个很复杂的对象,我们把这个工作分开来做,先定义并实现一个建造者类,在这个类中实现构建这个对象所需要的全部方法。再定义并实现一个导演类,把一个建造者类传给它,让它负责这些方法调用的逻辑次序和对象的组合,然后统一给客户端返回一个生成好的复杂对象。

原型模式

已经有了一个对象了,我们创建对象时直接复制它,不需要新建了。

适配器模式

一个类和另一个类有一些相似的操作,但是它们的形式是不一致的,需要有一个东西把它包裹起来,变成另一种比较合适的形式。

  • 类适配:创建新类,继承源类,并实现新接口,例如

    class  adapter extends oldClass  implements newFunc{}
  • 对象适配:创建新类持源类的实例,并实现新接口,例如 
    class adapter implements newFunc { private oldClass oldInstance ;}
  • 接口适配:创建新的抽象类实现旧接口方法。例如 
    abstract class adapter implements oldClassFunc { void newFunc();}

装饰器模式

一个类有一些方法,但是我们想让这些方法调用的时候多执行一些东西,于是可以定义一个装饰器的类,它和被修饰的类同时一个类的子类或是一个接口的实现,然后将这个被修饰的类委托给这个装饰器类,如果想使用这个修饰后的方法,只需要调用这个修饰器的方法就可以了。

代理模式

我想访问一个对象,但是这个对象出于多种考虑,比如细节复杂、需要控制访问、隐藏细节等,不能让别人直接使用,必须要使用一个中间层性质的代理类,对这个对象的所有访问都由这个代理类来完成。

外观模式

我现在有一个成套的系统,有若干接口、类,但是直接操作这些类是一个很复杂的过程,于是额外再定义一个总结性质的类,给几个比较有概括性的、简洁的方法去操作这个系统,以此来简化访问。

桥接模式

如果我现在有一个抽象的父类,和一些具体的子类,本来他们应该是一个继承的关系,但我认为这样会使两个类耦合过紧,于是强行使用委派、组合的方式,使两者可以相对独立的变化。具体就是在抽象类中实现一些基本操作,然后把一些需要细分的操作委派出去,可以把那些原来的子类统一到一个接口里,然后把这个接口和原来的父类组合。

组合模式

定义一个比较宽泛的类,一个具体的对象属于这个类,把这些具体的对象按一定方式组合起来也属于这个类。

享元模式

很多对象都需要用同一个对象,但他们都自己创建了一份保存,这样会造成内存大量浪费。把这一部分抽出来,只创建一份,供这些对象共同使用,就可以节省内存。

观察者模式

一组对象依赖于某一个对象,这个对象的状态的更新会影响这一组对象,于是把这组对象称为观察者,放在被观察者一个不定长数组的字段里,两者分别保存对方的引用,被观察者更新时会调用观察者的方法来提醒观察者。

访问者模式

我现在有一个类,上面有一些操作,但是我不想把它写到这个类里,所以我把这个功能单独拿出来,需要执行这个功能的时候,把这个类的引用给那个功能类,让那个功能类操作这个类。

状态模式

一个类,他的一些操作的具体过程是根据它当前的状态来决定的,而这个状态取决于当前环境的上下文。

备忘录模式

对一个类的对象的状态进行可持久化处理,方法是另外设立一个备忘录类,记录状态的变化过程,然后就可以恢复到某个历史状态。

策略模式

对于一个操作,实现它的算法有很多,我把这些算法每个都建立一个类,实现那个方法类的接口,在需要执行这个操作的地方,要运用某个算法,只需要把那个算法对应的类传进去就行了。

模板模式

一个操作,它的每一步可能有细节上的区别,但是它的大概框架是确定的,在执行各个步骤的时候,先用一些抽象类放在对应的位置,等随后再定义一些具体类去填充它。

迭代器模式

一个类,里面有一组元素,要按照某个次序一次访问这些元素,于是单独设立一个迭代器,无需暴露内部复杂实现,直接告诉你当前是哪个元素、下一个是哪个元素,就可以按照这种特定次序遍历这些元素了。

下面是分类介绍

单例模式

简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。

getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来也很容易,直接看demo吧

public class Singleton {private static Singleton singleton;private Singleton() {
}public static Singleton getInstance() {if (singleton == null) {singleton = new Singleton();}return singleton;
}
}public class Singleton {private static Singleton singleton;private Singleton() {
}public static Singleton getInstance() {if (singleton == null) {singleton = new Singleton();}return singleton;
}
}
 

按照我的习惯,我恨不得写满注释,怕你们看不懂,但是这个代码实在太简单了,所以我没写任何注释,如果这几行代码你都看不明白的话,那你可以洗洗睡了,等你睡醒了再来看我的博客说不定能看懂。

上面的是最基本的写法,也叫懒汉写法(线程不安全)下面我再公布几种单例模式的写法:

懒汉式写法(线程安全)
public class Singleton {  private static Singleton instance;  private Singleton (){}  public static synchronized Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }
}
饿汉式写法
public class Singleton {  private static Singleton instance = new Singleton();  private Singleton (){}  public static Singleton getInstance() {  return instance;  }
}
静态内部类
public class Singleton {  private static class SingletonHolder {  private static final Singleton INSTANCE = new Singleton();  }  private Singleton (){}  public static final Singleton getInstance() {  return SingletonHolder.INSTANCE;  }
}
枚举public enum Singleton {  INSTANCE;  public void whateverMethod() {  }
}

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏。

双重校验锁

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;  }
}

总结:我个人比较喜欢静态内部类写法和饿汉式写法,其实这两种写法能够应付绝大多数情况了。其他写法也可以选择,主要还是看业务需求吧。

观察者模式

对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式UML图

看不懂图的人端着小板凳到这里来,给你举个栗子:假设有三个人,小美(女,22),小王和小李。小美很漂亮,小王和小李是两个程序猿,时刻关注着小美的一举一动。有一天,小美说了一句:“谁来陪我打游戏啊。”这句话被小王和小李听到了,结果乐坏了,蹭蹭蹭,没一会儿,小王就冲到小美家门口了,在这里,小美是被观察者,小王和小李是观察者,被观察者发出一条信息,然后观察者们进行相应的处理,看代码:

public interface Person {//小王和小李通过这个接口可以接收到小美发过来的消息void getMessage(String s);
}
l这个接口相当于小王和小李的电话号码,小美发送通知的时候就会拨打getMessage这个电话,拨打电话就是调用接口,看不懂没关系,先往下看public class LaoWang implements Person {private String name = "小王";public LaoWang() {}@Overridepublic void getMessage(String s) {System.out.println(name + "接到了小美打过来的电话,电话内容是:" + s);}}public class LaoLi implements Person {private String name = "小李";public LaoLi() {}@Overridepublic void getMessage(String s) {System.out.println(name + "接到了小美打过来的电话,电话内容是:->" + s);}}
代码很简单,我们再看看小美的代码:public class XiaoMei {List<Person> list = new ArrayList<Person>();public XiaoMei(){}public void addPerson(Person person){list.add(person);}//遍历list,把自己的通知发送给所有暗恋自己的人public void notifyPerson() {for(Person person:list){person.getMessage("你们过来吧,谁先过来谁就能陪我一起玩儿游戏!");}}
}

我们写一个测试类来看一下结果对不对

public class Test {public static void main(String[] args) {XiaoMei xiao_mei = new XiaoMei();LaoWang lao_wang = new LaoWang();LaoLi lao_li = new LaoLi();//小王和小李在小美那里都注册了一下xiao_mei.addPerson(lao_wang);xiao_mei.addPerson(lao_li);//小美向小王和小李发送通知xiao_mei.notifyPerson();}
}
 

装饰者模式

对已有的业务逻辑进一步的封装,使其增加额外的功能,如Java中的IO流就使用了装饰者模式,用户在使用的时候,可以任意组装,达到自己想要的效果。 举个栗子,我想吃三明治,首先我需要一根大大的香肠,我喜欢吃奶油,在香肠上面加一点奶油,再放一点蔬菜,最后再用两片面包夹一下,很丰盛的一顿午饭,营养又健康。(ps:不知道上海哪里有卖好吃的三明治的,求推荐~)那我们应该怎么来写代码呢? 首先,我们需要写一个Food类,让其他所有食物都来继承这个类,看代码:

public class Food {private String food_name;public Food() {}public Food(String food_name) {this.food_name = food_name;}public String make() {return food_name;};
}

代码很简单,我就不解释了,然后我们写几个子类继承它:

//面包类
public class Bread extends Food {private Food basic_food;public Bread(Food basic_food) {this.basic_food = basic_food;}public String make() {return basic_food.make()+"+面包";}
}//奶油类
public class Cream extends Food {private Food basic_food;public Cream(Food basic_food) {this.basic_food = basic_food;}public String make() {return basic_food.make()+"+奶油";}
}//蔬菜类
public class Vegetable extends Food {private Food basic_food;public Vegetable(Food basic_food) {this.basic_food = basic_food;}public String make() {return basic_food.make()+"+蔬菜";}}
 

这几个类都是差不多的,构造方法传入一个Food类型的参数,然后在make方法中加入一些自己的逻辑,如果你还是看不懂为什么这么写,不急,你看看我的Test类是怎么写的,一看你就明白了

public class Test {public static void main(String[] args) {Food food = new Bread(new Vegetable(new Cream(new Food("香肠"))));System.out.println(food.make());}
}

看到没有,一层一层封装,我们从里往外看:最里面我new了一个香肠,在香肠的外面我包裹了一层奶油,在奶油的外面我又加了一层蔬菜,最外面我放的是面包,是不是很形象

Java常见的设计模式整理相关推荐

  1. java常见的设计模式

    在了解java常见的设计模式之前,我们要了解三个问题, 1.为什么要了解设计模式? 2.这些设计模式的是根据什么原则来设计的? 3.有哪些常见的设计模式? 为什么要了解设计模式? 因为设计模式代表了最 ...

  2. ☀️一张思维图带大家了解Java常见设计模式☀️《❤️记得收藏❤️》

    ☀️一张思维图带大家了解Java常见设计模式☀️<❤️记得收藏❤️> 目录

  3. Java设计模式整理

    Java设计模式整理 1.单例设计模式 所谓单例设计模式简单说就是无论程序如何运行,采用单例设计模式的类(Singleton类)永远只会有一个实例化对象产生,并且只提供一个全局的访问点 . 具体实现步 ...

  4. 高级 Java 面试通关知识点整理

    转载自 高级 Java 面试通关知识点整理 1.常用设计模式 单例模式:懒汉式.饿汉式.双重校验锁.静态加载,内部类加载.枚举类加载.保证一个类仅有一个实例,并提供一个访问它的全局访问点. 代理模式: ...

  5. java面试基础题整理(二)

    java面试基础题整理 文章目录 java面试基础题整理 前端技术(HTML.CSS.JS.JQuery等) 在js中怎么样验证数字? js中如何给string这个类型加方法? 谈谈js的定时器? 请 ...

  6. Java常见类库与工具及官网

    Java https://www.oracle.com/java/technologies/ OpenJDK https://openjdk.java.net/ w3c(万维网联盟) https:// ...

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

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

  8. Java常见排序算法之插入排序

    一.概述 本节由小千给大家分享Java常见排序算法之插入排序,之前我们说过排序是算法中的一部分.所以我们学习排序也是算法的入门,为了能让大家感受到排序是算法的一部分,我举个例子证明一下:比如麻将游戏, ...

  9. java中单例设计模式登记式单例类_java23种设计模式-创建型模式之单例模式

    单例模式(Singleton) 单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频 ...

最新文章

  1. 硅谷人眼中的2018年十大前沿科技预测
  2. 那些好用的小工具——Total Commander
  3. 三、Dockerfile的说明和编写
  4. 选择之后触_发宜常梳:4种材质的梳子,我们最常用的梳子却对头发最不好,该如何选择?...
  5. Xcode的Architectures和Valid Architectures的区别
  6. 冒泡排序和选择排序区别_你以为只是简单的排序?(一)
  7. TR069 ACS模拟器测试脚本
  8. 使用“管道”与“应用程序生命周期”重构:可插拔模块
  9. 移动端 js 弹出层内容滚动的时候,不影响body的滚动条处理
  10. 今日头条遭罚 94 万;快手、火山小视频整改「低俗」;Wi-Fi 万能钥匙被调查 | CSDN极客头条
  11. nginx编译安装和yum安装那个更好?
  12. unity linerenderer在Game窗口中任意画线
  13. android apk 微信登入_Android实现使用微信登录第三方APP的方法
  14. 测试网速_使用Speedtest CLI测试你的网速
  15. 计算机课翻转课堂教案,翻转课堂式教学
  16. 英文科技论文写作与学术报告2021秋期末考答案|网课期末考答案|学堂在线|清华大学管晓宏教授
  17. 全同态加密(FHE):BV方案、密钥切换、模约化、自举
  18. 一个匹配数字的正则表达式(带详细解释)
  19. android播放mp3方法,Android MediaPlayer 播放音频的方式
  20. Matlab基础——变量和语句

热门文章

  1. 99%品牌梦寐以求的爆款流量,小红书笔记搜索排名置顶黑科技!
  2. Radio Transmission
  3. FiddlerScript详解
  4. fasttext文本分类、训练词向量、词向量迁移
  5. VGGNet 与 GoogLeNet
  6. 哇塞!抽象工厂模式还能这样玩
  7. Cadence OrCAD Capture instance属性和occurences属性的区别
  8. Airtest IDE 自动化测试10——text和keyevent
  9. 搭建scrapy框架
  10. vue scss 一键更换主题色,字体等页面等页面大体样式