目录
- 设计模式的分类
- 创建型模式(5种)
- 1、单例模式
- 2、简单工厂模式
- 3、工厂方法模式
- 4、抽象工厂模式
- 5、原型模式(Clone)
- 结构型模式(7种)
- 1、代理模式
- 2、适配器模式
- 3、装饰者模式
- 4、桥接模式
- 5、外观模式
- 6、组合模式
- 7、享元模式
- 行为型模式(11种)
- 1、模板方法模式
- 2、策略模式
- 3、观察者模式
- 4、责任链模式
- 5、迭代子模式
- 6、命令模式
- 7、备忘录模式
- 8、状态模式
- 9、访问者模式
- 10、中介者模式
- 11、解释器模式
设计模式六大原则
单一职责原则
开闭原则
里氏替换原则
依赖倒置原则
接口隔离原则
迪米特法则
设计模式的分类
①创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
②结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
③行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
创建型模式(5种)
1、单例模式
饿汉式:类加载时对象就会导致实例对象被创建
package SheJiMoShi;
public class Singleton {
//1、定义私有的构造方法,不能给别人创建对象
private Singleton(){}
//2、饿汉式-------类加载时创建实例对象
private static Singleton singleton = new Singleton();
//3、静态方法以被获取到实例对象
public static Singleton getInstance(){
return singleton;
}
}
懒汉式:类加载不会导致实例对象被创建,而是在首次使用该对象时被创建(要考虑线程安全问题)
方式一:加synchronized锁
public class Singleton {
//1、定义私有的构造方法,不能给别人创建对象
private Singleton(){}
//2、懒汉式-------类加载时不会创建实例对象
private static Singleton singleton;
//3、静态方法以被获取到实例对象,加synchronized是为了解决懒汉式的线程安全问题!!!
public static synchronized Singleton getInstance(){
if(singleton == null){
singleton= new Singleton();
}
return singleton;
}
}
方式二:双重检查锁
public class Singleton {
//1、定义私有的构造方法,不能给别人创建对象
private Singleton(){}
//2、懒汉式-------类加载时不会创建实例对象,加上volatile关键字解决空指针异常问题
private static volatile Singleton singleton;
//3、静态方法以被获取到实例对象,通过双重检查方式解决线程安全问题!!!!
public static Singleton getInstance(){
//第一次判断
if(singleton == null){
synchronized (Singleton.class){
//第二次判断
if (singleton == null){
singleton= new Singleton();
}
}
}
return singleton;
}
}
测试:
package SheJiMoShi;
public class Test {
public static void main(String[] args) {
//获取单例实例对象
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1);
}
}
项目中的应用场景:①Spring中的Bean对象的默认创建方式
②线程池的线程也是单例的,可以重复利用的
2、简单工厂模式
实体类 :
//接口
public interface Shape {
void draw();
}
//圆实现类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("我要画圆");
}
}
//三角形实现类
public class Rectangle implements Shape{
@Override
public void draw() {
System.out.println("我要画三角形");
}
}
图纸类:用来画画,但是需要工厂提供专门的画笔,画圆需要画圆的笔,画三角形需要三角形的笔
//画画图纸
public class Page {
public static void main(String[] args) {
//定义工厂对象
ShapeFactory shapeFactory = new ShapeFactory();
Scanner scanner = new Scanner(System.in);
while (true){
System.out.print("快来画画呀,你想画啥: ");
String name = scanner.nextLine();
//通过工厂生产对象
Shape createshape = shapeFactory.createshape(name);
createshape.draw();
}
}
}
简单工厂类:根据画什么画去生产对应画画的笔
//简单工厂类
public class ShapeFactory {
//工厂创建对象
public Shape createshape(String name){
if("circle".equals(name)){
return new Circle();
}
else if("rentangle".equals(name)){
return new Rectangle();
}
else{
throw new RuntimeException();
}
}
}
静态工厂类:可以替换上面的工厂类
public class ShapeFactory {
//工厂创建对象
public static Shape createshape(String name){
if("circle".equals(name)){
return new Circle();
}
else if("rentangle".equals(name)){
return new Rectangle();
}
else{
throw new RuntimeException();
}
}
}
优缺点:简单工厂模式封装了创建对象的过程,把对象和业务逻辑层分开,降低耦合,避免修改客户端代码。但是当我们需要扩展类型时,需要去直接修改工厂类,违背了开闭原则。
3、工厂方法模式
定义图形接口以及类:
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("我要画圆");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("我要画三角形");
}
}
定义抽象工厂接口,以及子类具体工厂实现:
//抽象工厂
public interface Factory {
//创建图形的方法
Shape createPain();
}
//圆工厂,生产圆
public class CircleFactory implements Factory{
@Override
public Shape createPain() {
return new Circle();
}
}
//三角形工厂,生产三角形
public class RectangleFactory implements Factory{
@Override
public Shape createPain() {
return new Rectangle();
}
}
最后定义一张纸画画,以及定义一个人去拿纸画画:
//画画图纸
public class Page {
private Factory factory;
public void setFactory(Factory factory) {
this.factory = factory;
}
public Shape draw(){
Shape shape = factory.createPain();
return shape;
}
}
public class Kid {
public static void main(String[] args) {
//拿纸
Page page = new Page();
//想要画什么
page.setFactory(new CircleFactory());
//去从工厂拿,拿到了圆
Shape shape = page.draw();
//我就直接开画
shape.draw();
}
}
优缺点:工厂方法模式满足了开闭原则,当我们需要添加或者需要拓展工厂类的时候,直接去创建抽象工厂接口的子类去重写方法然后进行扩展即可。但是每增加一个产品都要增加一个具体类和工厂类,又会增加系统复杂度。
4、抽象工厂模式
定义产品接口和具体实现类:
//手机接口
public interface Phone {
void buyphone();
}
//小米手机
public class Xiaomiphone implements Phone{
@Override
public void buyphone() {
System.out.println("我要买小米14");
}
}
//华为手机
public class Huaweiphone implements Phone{
@Override
public void buyphone() {
System.out.println("我要买HUAWEI Mate 60");
}
}
//车接口
public interface Car {
void buycar();
}
//小米汽车
public class Xiaomicar implements Car{
@Override
public void buycar() {
System.out.println("我要买小米su7");
}
}
//华为汽车
public class Huaweicar implements Car{
@Override
public void buycar() {
System.out.println("我要买智界S6");
}
}
定义抽象工厂接口和产品族工厂具体类:
//抽象工厂
public interface Factory {
//生产手机
Phone createphone();
//生产车
Car createcar();
}
//小米工厂
public class XiaomiFactory implements Factory{
@Override
public Phone createphone() {
return new Xiaomiphone();
}
@Override
public Car createcar() {
return new Xiaomicar();
}
}
//华为工厂
public class HuaweiFactory implements Factory{
@Override
public Phone createphone() {
return new Huaweiphone();
}
@Override
public Car createcar() {
return new Huaweicar();
}
}
商店:
public class Store {
private Factory factory;
public void setFactory(Factory factory) {
this.factory = factory;
}
public static void main(String[] args) {
//创建商店
Store store = new Store();
//我想买小米手机,先创建小米工厂
store.setFactory(new XiaomiFactory());
//再去工厂拿
Phone phone = store.factory.createphone();
phone.buyphone();
//我又要买小米su7,不用再次创建小米工厂
Car car = store.factory.createcar();
car.buycar();
}
}
抽象工厂模式优缺点:一个产品族的产品直接由一个工厂生产。但是当要新增一个产品时,全部的工厂类都需要修改。
工厂模式的实际应用场景:①Spring IOC对Bean的生产和管理。
②数据库连接。
5、原型模式(Clone)
原型类:
//实现Cloneable接口
public class ProtoTypeDemo implements Cloneable{
//重写Clone方法
@Override
public ProtoTypeDemo clone() throws CloneNotSupportedException {
return (ProtoTypeDemo) super.clone();
}
}
测试类:
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
//创建一个原型类对象
ProtoTypeDemo protoTypeDemo = new ProtoTypeDemo();
//获取克隆对象
ProtoTypeDemo clone = protoTypeDemo.clone();
System.out.println("clone = " + clone);
System.out.println(protoTypeDemo == clone);
}
}
项目中的应用场景:①Spring中的Bean可通过scrop设置为prototype原型模式
②对象的赋值和克隆
结构型模式(7种)
1、代理模式
分为静态代理和动态代理。动态代理又分为jdk动态代理和cglib动态代理。
静态代理:
//卖火车票接口
public interface SellTickets {
void sell();
}
//主题类
public class TrainStation implements SellTickets{
@Override
public void sell() {
System.out.println("我是火车站,我来卖火车票");
}
}
//代理类,静态代理,即在编译时完成了代理
public class ProxyPoint implements SellTickets{
private TrainStation trainStation = new TrainStation();
@Override
public void sell() {
System.out.println("我是代售点,我来帮火车站卖火车票,并且赚取差价");
trainStation.sell();
}
}
//客户测试类
public class Client {
public static void main(String[] args) {
//我去代售点买票
ProxyPoint proxyPoint = new ProxyPoint();
//代售点卖票
proxyPoint.sell();
}
}
JDK动态代理:
//买火车票接口
public interface SellTickets {
void sell();
}
//主题类
public class TrainStation implements SellTickets {
@Override
public void sell() {
System.out.println("我是火车站,我来卖火车票");
}
}
动态代理程序
//动态代理程序,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler{
//最终我就是要卖票,所以创建卖票动作
private SellTickets sellTickets;
public void setSellTickets(SellTickets sellTickets) {
this.sellTickets = sellTickets;
}
//获取到代理对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),sellTickets.getClass().getInterfaces(),this);
}
//代理对象(代售点)的操作
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是代售点,帮火车站卖票,我还要赚差价");
//通过反射执行,method是对接口中的方法进行封装了,实际上执行的就是接口中的方法
Object invoke = method.invoke(sellTickets, args);
return invoke;
}
}
测试类
public class Client {
public static void main(String[] args) {
//我要卖票,肯定先找火车站对象
TrainStation trainStation = new TrainStation();
//生成一个动态代理处理程序
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
//将火车站对象放进程序中
proxyInvocationHandler.setSellTickets(trainStation);
//然后获取到火车站的代理对象 --->代售点
SellTickets proxy = (SellTickets) proxyInvocationHandler.getProxy();
//我通过代售点去买票就ok了
proxy.sell();
}
}
CGlib动态代理:
先引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
//主题类
public class TrainStation{
public void sell() {
System.out.println("我是火车站,我来卖火车票");
}
}
public class ProxyFactory implements MethodInterceptor {
private TrainStation trainStation = new TrainStation();
public TrainStation getProxy(){
//创建Enhance对象
Enhancer enhancer = new Enhancer();
//设置父类的字节码对象
enhancer.setSuperclass(TrainStation.class);
//设置回调函数
enhancer.setCallback(this);
//创建代理对象
TrainStation trainStation = (TrainStation) enhancer.create();
return trainStation;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("我是代售点,我帮火车站卖票并且收取差价");
//调用目标对象的方法
Object invoke = method.invoke(trainStation, objects);
return invoke;
}
}
public class Client {
public static void main(String[] args) {
//创建工厂对象
ProxyFactory proxyFactory = new ProxyFactory();
//获取代理对象
TrainStation proxy = proxyFactory.getProxy();
//调用代理对象的买票方法
proxy.sell();
}
}
JDK动态代理与CGLIB动态代理的区别:
①JDK动态代理底层是反射机制,使用反射机制生成的代理对象以及调用目标方法,而CGlib是采用ASM字节码生成框架,使用字节码技术生成子类。
②JDK动态代理只能对实现接口的类进行代理,而CGLib使用的是继承机制,是针对类实现代理,因此无法对final修饰的类或者方法进行代理。
③JDK代理执行效率低,CGlib执行效率高。
项目中的应用场景:①Spring中AOP就是jdk的动态代理。
2、适配器模式
将一个类的接口转换为用户希望的另一个接口,使得原本接口不兼容的类可以一起工作。
两个接口和实现类:
public interface TFCard {
//从TF卡读数据
String readtf();
//往TF卡写数据
void writetf(String msg);
}
//适配者类
public class TFCardimpl implements TFCard{
@Override
public String readtf() {
return "我是TF";
}
@Override
public void writetf(String msg) {
System.out.println("我往TF卡中写了数据"+msg);
}
}
//目标接口
public interface SDCard {
//从SD卡读数据
String readsd();
//往SD卡写数据
void writesd(String msg);
}
public class SDCardimpl implements SDCard{
@Override
public String readsd() {
return "我是SD";
}
@Override
public void writesd(String msg) {
System.out.println("我往SD卡中写了数据"+msg);
}
}
电脑类: 电脑只能操作SD卡,不能直接操作TF卡
//计算机类,只能操作SD卡,不能操作TF卡
public class Computer {
//从SD卡中读数据
public String readsd(SDCard sdCard){
return sdCard.readsd();
}
//往SD卡中写数据
public void writesd(SDCard sdCard,String msg){
sdCard.writesd(msg);
}
}
定义一个适配器类:将对SD卡的操作适配到TF卡上去
//适配器类,表面上是操作SD卡,其实已经是适配到TF卡
public class TF_to_SD_Adaptor extends TFCardimpl implements SDCard {
@Override
public String readsd() {
String readtf = readtf();
return readtf;
}
@Override
public void writesd(String msg) {
writetf(msg);
}
}
客户端:
public class Client {
public static void main(String[] args) {
//创建电脑
Computer computer = new Computer();
//电脑已经支持SD卡,可直接操作
String readsd = computer.readsd(new SDCardimpl());
System.out.println("我从SD卡中读到的数据是: " + readsd);
computer.writesd(new SDCardimpl(),"我要往SD卡中存数据");
//但是我现在要从TF卡中读数据
//定义一个适配器,即在电脑上连接一个拓展坞去适配到TF
TF_to_SD_Adaptor adaptor = new TF_to_SD_Adaptor();
String readsd1 = computer.readsd(adaptor);
System.out.println("我从TF卡中读到的数据是: "+ readsd1);
computer.writesd(adaptor,"我要往TF卡中存数据");
}
}
项目中的应用场景:①SpringMVC中的处理器适配器HandlerAdaptor。
②SpringAOP中的通知适配器AdvisorAdaptor。
3、装饰者模式
装饰者模式在不改变一个对象的本身的基础上给对象添加额外的新行为。
//抽象构建类--->抽象加密类
public interface Cipher {
//定义加密方法
public String jiami(String passward);
}
//具体构建类---->简单加密类
public class SimpleCipher implements Cipher{
//进行简单的加密,ASCII+5
@Override
public String jiami(String passward) {
String str="";
for (int i = 0; i < passward.length(); i++) {
char temp = passward.charAt(i);
temp+=5;
str+=temp;
}
return str;
}
}
//抽象装饰类---->加密装饰类
public class CipherDecorator implements Cipher{
private Cipher cipher;
public CipherDecorator(Cipher cipher) {
this.cipher = cipher;
}
//定义要装饰的加密方法
@Override
public String jiami(String passward) {
return cipher.jiami(passward);
}
}
//具体装饰类---->复杂加密类
public class ComplexCipher extends CipherDecorator{
public ComplexCipher(Cipher cipher){
super(cipher);
}
//重写父方法,实现复杂加密
@Override
public String jiami(String passward) {
return new StringBuffer(passward).reverse().toString();
}
}
//具体装饰类---->高级加密类
public class AdvancedCipher extends CipherDecorator{
public AdvancedCipher(Cipher cipher) {
super(cipher);
}
//重写父方法,实现高级加密
@Override
public String jiami(String passward) {
return passward.replaceAll("h","noWay");
}
}
//测试类,输入密码,进行装饰加密
public class Client {
public static void main(String[] args) {
String passward = "abcfjhC";
Cipher sc,cc,ac;
sc= new SimpleCipher();
String jiami = sc.jiami(passward);
System.out.println("简单加密后的密码是 = " + jiami);
cc= new ComplexCipher(sc);
String jiami1 = cc.jiami(jiami);
System.out.println("复杂加密后的密码是 = " + jiami1);
ac=new AdvancedCipher(sc);
String jiami2 = ac.jiami(jiami1);
System.out.println("高级加密后的密码是 = " + jiami2);
}
}
装饰者模式可以带来比继承更加灵活的扩展功能,完美的遵循开闭原则。与代理模式的区别:装饰者是为了增强目标对象,而代理模式是为了保护和隐藏目标对象。
4、桥接模式
5、外观模式
6、组合模式
7、享元模式
行为型模式(11种)-----流程控制
1、模板方法模式
抽象类:
//抽象类,定义模板方法和基本方法
public abstract class AbstractClass {
//模板方法
public final void streat(){
arrived();
order();
eat();
pay();
}
//到达--基本方法
public void arrived(){
System.out.println("到达饭馆");
}
//点单--抽象方法
public abstract void order();
//吃东西--抽象方法
public abstract void eat();
//买单--基本方法
public void pay(){
System.out.println("买单");
}
}
抽象类的子类:
//我请客
public class My extends AbstractClass{
@Override
public void order() {
System.out.println("我请客,我要点.....");
}
@Override
public void eat() {
System.out.println("开吃,全部都算我的");
}
}
测试类:
public class Client {
public static void main(String[] args) {
My my = new My();
my.streat();
}
}
优缺点:提高代码复用性。在一个类中形式化定义算法,由子类实现细节但不改变算法的结构。
项目中使用场景:①JDBCTemplate。
②RedisTemplate。
③RestTemplate。
2、策略模式
定义一系列的算法,将每一个算法封装起来,并让他们可以相互替换。
抽象策略类和具体策略类:
//抽象策略类
public abstract class Celue {
void show(){};
}
//具体策略类A--买一送一
public class A extends Celue{
@Override
void show() {
System.out.println("策略A:买一送一");
}
}
//具体策略类B--满200减50
public class B extends Celue{
@Override
void show() {
System.out.println("策略A:满200减50");
}
}
//具体策略类C--满1000减300
public class C extends Celue{
@Override
void show() {
System.out.println("策略C:满1000减300");
}
}
环境类:将策略聚合
//销售员--环境类
public class SaleMan {
private Celue celue;
public SaleMan(Celue celue) {
this.celue = celue;
}
//由销售员展示活动
public void salemanShow(){
celue.show();
}
}
测试类:
public class Client {
public static void main(String[] args) {
//创建销售员,并且表明要参与哪个活动
SaleMan saleMan = new SaleMan(new A());
//销售员展示活动
saleMan.salemanShow();
}
}
优缺点:策略之间可以相互切换,新增策略只需要直接添加一个策略类即可,避免了if else语句。客户端需要知道所有的策略进行选择用哪个。
项目中使用场景:①选择支付,用户选择微信支付、支付宝支付、银行卡支付。
②选择操作数据库,系统中展示了一系列文章,你点击了娱乐文章,则需要在娱乐表中的浏览量+1,点击军事类文章就去军事表中的浏览量+1。即更新浏览量需要更新不同的表
3、观察者模式
也叫作发布-订阅模式,定义了一种一对多的依赖关系,多个观察者对象同时监听某一个主题对象,这个主题对象在变化的时候会通知所有的观察者对象,使他们能够自动更新自己。
抽象主题类和具体主题类:
//抽象主题类
public interface Subject {
//添加观察者对象
void attch(Observer observer);
//删除观察者对象
void delete(Observer observer);
//通知更新
void notify(String msg);
}
//具体主题类
public class TopicSubject implements Subject{
List<Observer> list = new ArrayList<>();
//添加观察者
@Override
public void attch(Observer observer) {
list.add(observer);
}
//删除观察者
@Override
public void delete(Observer observer) {
list.remove(observer);
}
//通知所有的观察者
@Override
public void notify(String msg) {
for (Observer observer : list) {
observer.update("各位各位,更新啦,内容是"+msg);
}
}
}
观察者抽象类和观察者具体类:
//抽象观察者类
public interface Observer {
//收到通知
void update(String msg);
}
//具体观察者类1
public class Server01 implements Observer{
@Override
public void update(String msg) {
System.out.println("Server01收到通知:"+msg);
}
}
//具体观察者类2
public class Server02 implements Observer{
@Override
public void update(String msg) {
System.out.println("Server02收到通知:"+msg);
}
}
//具体观察者类3
public class Server03 implements Observer{
@Override
public void update(String msg) {
System.out.println("Server03收到通知:"+msg);
}
}
测试类:
public class Client {
public static void main(String[] args) {
//创建主题对象
TopicSubject topicSubject = new TopicSubject();
//创建观察者对象
Server01 server01 = new Server01();
Server02 server02 = new Server02();
Server03 server03 = new Server03();
//主题对象添加观察者/监听者
topicSubject.attch(server01);
topicSubject.attch(server02);
topicSubject.attch(server03);
topicSubject.notify("更新今天是7.3号");
}
}
优缺点: 降低耦合,可以实现广播机制。缺点:如果观察者很多的话,会耗时很长时间发消息。
项目中的应用场景:①Socket群聊。
②RabbitMQ的消息队列,生产者发消息到队列中,队列广播给所有的消费者
③Spring中的事件监听机制,ApplicationListener。容器发布一个ApplicationEvent事件会被通知到实现了ApplicationListener接口的Bean。
4、责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过把请求的发送者和接收者解耦,将多个对象连接成一个链,并沿着这条链传递请求,直到有一个对象能够处理它为止,从而避免了请求的发送者和接收者之间的直接耦合。
抽象接口类:
//抽象处理类
public interface Handler {
void setNextHandler(Handler handler);
boolean handler(int amount);
}
具体的处理器类:
//三级领导
public class Leader03 implements Handler{
private Handler nexthandler;
//定义下一级领导
@Override
public void setNextHandler(Handler handler) {
this.nexthandler=handler;
}
//处理方法
@Override
public boolean handler(int amount) {
if(amount<1000){
System.out.println("小钱,我小主管直接批了");
return true;
}
System.out.println("你要的太多了,我没这个权利,得问我的上级->经理");
return nexthandler.handler(amount);
}
}
//二级领导
public class Leader02 implements Handler{
private Handler nexthandler;
@Override
public void setNextHandler(Handler handler) {
this.nexthandler=handler;
}
@Override
public boolean handler(int amount) {
if(amount<5000){
System.out.println("ok,我经理直接批了");
return true;
}
System.out.println("你要的太多了,我没这个权利,得问我的上级->董事长");
return nexthandler.handler(amount);
}
}
//一级领导
public class Leader01 implements Handler{
private Handler nexthandler;
@Override
public void setNextHandler(Handler handler) {
this.nexthandler=handler;
}
@Override
public boolean handler(int amount) {
if(amount<10000){
System.out.println("行吧,我董事长直接批了");
return true;
}
System.out.println("你要的太多了,本公司满足不了你");
return false;
}
}
测试类:
//测试类
public class Client {
public static void main(String[] args) {
//先把领导定义出来
Leader01 leader01 = new Leader01();
Leader02 leader02 = new Leader02();
Leader03 leader03 = new Leader03();
//将领导分级
leader03.setNextHandler(leader02);
leader02.setNextHandler(leader01);
System.out.println("领导,我要开发软件,需要成本费:4000");
int amount = 6000;
if (leader03.handler(amount) == true) {
System.out.println("感谢领导,我一定好好干");
}else{
System.out.println("我去你的穷公司,这点钱都不批");
}
}
}
优缺点:降低对象间的耦合度,增强了系统的可扩展性并且简化了对象之间的连接。缺点是当处理链很长的时候会影响到系统性能,不能保证每个请求一定被处理。
项目中的应用场景:①过滤器Filter或者说拦截器。preHandler-postHandler-afterHandler
②SpringMVC的执行流程。
5、迭代器模式
6、命令模式
将请求(命令)封装成对象,使得可以用不同的请求对客户端进行参数化,具体的请求可以在运行时更改、排队或记录,它讲发出者和接收者解耦(顺序:发出者-->命令-->接收者)其本质就是:封装请求
命令接口:
//命令接口
public interface Command {
//点菜
void order(String msg);
//撤销
void cancel(String msg);
}
顾客类:
//顾客,调用者
public class Comsumer {
//顾客找到服务员
private Command command;
public Comsumer(Command command) {
this.command = command;
}
//点菜
public void eat(String msg){
System.out.println("我是顾客,我要吃"+msg);
command.order(msg);
}
//退菜
public void canceleat(String msg){
System.out.println("我是顾客,我要退"+msg);
command.cancel(msg);
}
}
服务员类:
//具体命令类---命令模式核心,将命令封装成对象
public class OrderCommand implements Command{
//定义厨师
private Chef chef;
public OrderCommand(Chef chef) {
this.chef = chef;
}
//顾客点单,通知后厨
@Override
public void order(String msg) {
System.out.println("我是服务员,顾客点单"+msg+"我要通知厨师制作");
chef.cook(msg);
}
//顾客退单,通知后厨
@Override
public void cancel(String msg) {
System.out.println("我是服务员,顾客退单"+msg+"我要通知厨师停止制作");
chef.cancelcook(msg);
}
}
厨师类:
//厨师,接收者
public class Chef {
//收到命令,制作
public void cook(String msg){
System.out.println("我是厨师,我收到命令,需要制作"+msg);
}
//收到命令,停止
public void cancelcook(String msg){
System.out.println("我是厨师,我收到命令,需要终止制作"+msg);
}
}
测试类:
public class Client {
public static void main(String[] args) {
//创建厨师
Chef chef = new Chef();
//创建服务员,可创建多个服务员
OrderCommand orderCommand = new OrderCommand(chef);
//创建顾客,可创建多个顾客
Comsumer comsumer = new Comsumer(orderCommand);
//可开多个线程点单
comsumer.eat("宫保鸡丁");
}
}
优缺点:解耦合,扩展灵活,增加删除命令方便。缺点是系统结构复杂度提高。
项目中的应用场景:①消息队列。
②Statement。SQL语句被封装成Statement对象,然后由数据库驱动程序执行命令。
③Runnable。Runnable接口封装了需要执行的任务,然后可以交给Thread线程调用start方法去执行。
7、备忘录模式
8、状态模式
状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,看起来就像是对象的类发生了改变。状态模式将状态封装成独立的类,并将对状态的行为委托给当前状态对象。