23种设计模式之行为型模型

在前面的两个帖子中,我们已经整理好23种设计模式之创建型模型(5种)和结构型模型(7种),接下来整理行为型模型(11种).

模板方法模式

模板方法模式又叫模板模式,在一个抽象类公开定义了执行他的方法模板,它的子类可以按照需求重写方法实现,但调用将以抽象类中定义的方式进行.

简单说,模板方法模式定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法结构,就可以重定义该算法的某些特定步骤.

使用场景:

编写制作豆浆的程序,

1.制作豆浆的流程,选材,添加配料,浸泡,放到豆浆机打碎

2.通过添加不同的配料,可以制作不同口味的豆浆.其中选材,浸泡和放到豆浆机打碎的步骤对于制作每种口味的豆浆都是一样的.

uml类图:

1.AbstractClass抽象类,类中实现了模板方法,定义了算法骨架,具体子类需要去实现.

2.ConcreteClass实现抽象方法operation2,3,4以完成算法中特殊要求子类的步骤.

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design12;

//抽象类,表示豆浆
public abstract class SoyaMilk {

	//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
	final void make() {
		
		select(); 
		addCondiments();
		soak();
		beat();
		
	}
	
	//选材料
	void select() {
		System.out.println("第一步:选择好的新鲜黄豆  ");
	}
	
	//添加不同的配料, 抽象方法, 子类具体实现
	abstract void addCondiments();
	
	//浸泡
	void soak() {
		System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
	}
	 
	void beat() {
		System.out.println("第四步:黄豆和配料放到豆浆机去打碎  ");
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design12;

public class RedBeanSoyaMilk extends SoyaMilk {

	@Override
	void addCondiments() {
		System.out.println(" 加入上好的红豆 ");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design12;

public class PeanutSoyaMilk extends SoyaMilk {

	@Override
	void addCondiments() {
		System.out.println(" 加入上好的花生 ");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design12;

public class Client {

	public static void main(String[] args) {
		//制作红豆豆浆
		
		System.out.println("----制作红豆豆浆----");
		SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
		redBeanSoyaMilk.make();
		
		System.out.println("----制作花生豆浆----");
		SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
		peanutSoyaMilk.make();
	}

}

模板方法中钩子方法:

1.在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为钩子

2.还是以豆浆为例子,我们需要做一个不添加任何配料的纯豆浆,代码如下:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design12.improve;

//抽象类,表示豆浆
public abstract class SoyaMilk {

	//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
	final void make() {
		
		select(); 
		if(customerWantCondiments()) {
			addCondiments();
		}
		soak();
		beat();
		
	}
	
	//选材料
	void select() {
		System.out.println("第一步:选择好的新鲜黄豆  ");
	}
	
	//添加不同的配料, 抽象方法, 子类具体实现
	abstract void addCondiments();
	
	//浸泡
	void soak() {
		System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
	}
	 
	void beat() {
		System.out.println("第四步:黄豆和配料放到豆浆机去打碎  ");
	}
	
	//钩子方法,决定是否需要添加配料
	boolean customerWantCondiments() {
		return true;
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design12.improve;

public class PureSoyaMilk extends SoyaMilk{

	@Override
	void addCondiments() {
		//空实现
	}
	
	@Override
	boolean customerWantCondiments() {
		return false;
	}
 
}
package com.hjm.shd.shardingspheredemo.designPatterns.design12.improve;

public class PeanutSoyaMilk extends SoyaMilk {

	@Override
	void addCondiments() {
		System.out.println(" 加入上好的花生 ");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design12.improve;

public class RedBeanSoyaMilk extends SoyaMilk {

	@Override
	void addCondiments() {
		System.out.println(" 加入上好的红豆 ");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design12.improve;

public class Client {

	public static void main(String[] args) {
		//制作红豆豆浆
		
		System.out.println("----制作红豆豆浆----");
		SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
		redBeanSoyaMilk.make();
		
		System.out.println("----制作花生豆浆----");
		SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
		peanutSoyaMilk.make();
		
		System.out.println("----制作纯豆浆----");
		SoyaMilk pureSoyaMilk = new PureSoyaMilk();
		pureSoyaMilk.make();
	}

}

模版方法模式在springIOC中源码分析:

模板方法模式优缺点:

1.算法只存在于一个地方,也就是在父类中,一般情况下都加上final关键字,防止子类重写模板方法.

2.实现了最大化代码复用,父类的模板方法和已实现的某些步骤会被子类继承而直接使用

3.既统一了算法,也提供了很大的灵活性.父类的模板方法确保了算法结构保持不变,同时由子类提供部分步骤的实现.

4.不足之处为 ,每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大.

模板方法使用场景:

当要完成在某个过程,该过程需要执行一系列步骤,这一系列步骤基本相同,但个别步骤实现可能不同,通常考虑模板方法模式.

命令模式

命令模式:在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需要在程序运行时指定具体的请求接收者即可,此时可以使用命令模式.

命令模式可以理解为 将军(Invoker)通过发送命令(Command)来指挥士兵(Receiver)

原理类图如下:

1.Invoker是调用这角色

2.Command是命令角色,需要执行的所有命令都在这里,可以使接口或者抽象类

3.Receiver接收者角色,知道如何实施和执行一个请求的操作

4.ConcreteCommand 将一个接收者对象与一个动作绑定,调用接收者相应的操作,实现execute

使用场景:

智能生活项目需求

1.我们有一套智能家电,电灯,电视机,冰箱,洗衣机,我们只要在手机上安装app就可以控制这些家电工作.这些家电来自不同的厂商,我们不可能为每一种家电都安装一个app,分别控制,我们想要一个app控制所有的家电

2.要实现一个app控制所有智能家电的需求,则每个智能家电的厂商都要给我们提供一个统一的接口调用,这时可以考虑使用命令模式

命令模式uml类图:

示例要求图:遥控器样式

撤销操作,只撤销前一步的操作.

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design13;


//创建命令接口
public interface Command {

	//执行动作(操作)
	public void execute();
	//撤销动作(操作)
	public void undo();
}
package com.hjm.shd.shardingspheredemo.designPatterns.design13;

//电灯接收者
public class LightReceiver {

	public void on() {
		System.out.println(" 电灯打开了.. ");
	}
	
	public void off() {
		System.out.println(" 电灯关闭了.. ");
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design13;

public class LightOffCommand implements Command {

	// 聚合LightReceiver

	LightReceiver light;

	// 构造器
	public LightOffCommand(LightReceiver light) {
			super();
			this.light = light;
		}

	@Override
	public void execute() {
		// 调用接收者的方法
		light.off();
	}

	@Override
	public void undo() {
		// 调用接收者的方法
		light.on();
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design13;

public class LightOnCommand implements Command {

	//聚合LightReceiver
	
	LightReceiver light;
	
	//构造器
	public LightOnCommand(LightReceiver light) {
		super();
		this.light = light;
	}
	
	@Override
	public void execute() {
		//调用接收者的方法
		light.on();
	}

	

	@Override
	public void undo() {
		//调用接收者的方法
		light.off();
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design13;

/**
 * 没有任何命令,即空执行: 用于初始化每个按钮, 当调用空命令时,对象什么都不做
 * 其实,这样是一种设计模式, 可以省掉对空判断
 * @author Administrator
 *
 */
public class NoCommand implements Command {

	@Override
	public void execute() {

		
	}

	@Override
	public void undo() {

		
	}

}

创建遥控器类

package com.hjm.shd.shardingspheredemo.designPatterns.design13;

public class RemoteController {

	// 开 按钮的命令数组
	Command[] onCommands;
	Command[] offCommands;

	// 执行撤销的命令
	Command undoCommand;

	// 构造器,完成对按钮初始化

	public RemoteController() {

		onCommands = new Command[5];
		offCommands = new Command[5];

		for (int i = 0; i < 5; i++) {
			onCommands[i] = new NoCommand();
			offCommands[i] = new NoCommand();
		}
	}

	// 给我们的按钮设置你需要的命令
	public void setCommand(int no, Command onCommand, Command offCommand) {
		onCommands[no] = onCommand;
		offCommands[no] = offCommand;
	}

	// 按下开按钮
	public void onButtonWasPushed(int no) { // no 0
		// 找到你按下的开的按钮, 并调用对应方法
		onCommands[no].execute();
		// 记录这次的操作,用于撤销
		undoCommand = onCommands[no];

	}

	// 按下开按钮
	public void offButtonWasPushed(int no) { // no 0
		// 找到你按下的关的按钮, 并调用对应方法
		offCommands[no].execute();
		// 记录这次的操作,用于撤销
		undoCommand = offCommands[no];

	}
	
	// 按下撤销按钮
	public void undoButtonWasPushed() {
		undoCommand.undo();
	}

}

创建一个客户端用于调用,后续加上电视机的才能使用

package com.hjm.shd.shardingspheredemo.designPatterns.design13;

public class Client {

	public static void main(String[] args) {
		
		//使用命令设计模式,完成通过遥控器,对电灯的操作
		
		//创建电灯的对象(接受者)
		LightReceiver lightReceiver = new LightReceiver();
		
		//创建电灯相关的开关命令
		LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
		LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
		
		//需要一个遥控器
		RemoteController remoteController = new RemoteController();
		
		//给我们的遥控器设置命令, 比如 no = 0 是电灯的开和关的操作
		remoteController.setCommand(0, lightOnCommand, lightOffCommand);
		
		System.out.println("--------按下灯的开按钮-----------");
		remoteController.onButtonWasPushed(0);
		System.out.println("--------按下灯的关按钮-----------");
		remoteController.offButtonWasPushed(0);
		System.out.println("--------按下撤销按钮-----------");
		remoteController.undoButtonWasPushed();
		
		
		System.out.println("=========使用遥控器操作电视机==========");

		TVReceiver tvReceiver = new TVReceiver();

		TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);
		TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);

		//给我们的遥控器设置命令, 比如 no = 1 是电视机的开和关的操作
		remoteController.setCommand(1, tvOnCommand, tvOffCommand);

		System.out.println("--------按下电视机的开按钮-----------");
		remoteController.onButtonWasPushed(1);
		System.out.println("--------按下电视机的关按钮-----------");
		remoteController.offButtonWasPushed(1);
		System.out.println("--------按下撤销按钮-----------");
		remoteController.undoButtonWasPushed();

	}

}

扩展电视机功能时需要新增的类

package com.hjm.shd.shardingspheredemo.designPatterns.design13;

public class TVReceiver {
	
	public void on() {
		System.out.println(" 电视机打开了.. ");
	}
	
	public void off() {
		System.out.println(" 电视机关闭了.. ");
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design13;

public class TVOffCommand implements Command {

	// 聚合TVReceiver

	TVReceiver tv;

	// 构造器
	public TVOffCommand(TVReceiver tv) {
		super();
		this.tv = tv;
	}

	@Override
	public void execute() {

		// 调用接收者的方法
		tv.off();
	}

	@Override
	public void undo() {

		// 调用接收者的方法
		tv.on();
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design13;

public class TVOnCommand implements Command {

	// 聚合TVReceiver

	TVReceiver tv;

	// 构造器
	public TVOnCommand(TVReceiver tv) {
		super();
		this.tv = tv;
	}

	@Override
	public void execute() {

		// 调用接收者的方法
		tv.on();
	}

	@Override
	public void undo() {

		// 调用接收者的方法
		tv.off();
	}
}

命令模式在Spring框架JDBCTemplate应用源码分析:

命令模式优缺点:

1.将发起请求的对象与执行请求的对象解耦.命令对象起到了纽带桥梁的作用

2.容易设计一个命令队列,只要把命令对象放到队列,就可以多线程执行命令

3.容易实现对请求的撤销和重做.

4.命令模式可能导致某些系统有过多的具体命令类,增加了系统的复杂度.

5.命令模式经典的应用场景:界面的一个按钮都是一条命令,模拟CMD(DOS命令)订单的撤销/恢复,触发-反馈机制.

访问者模式

访问者模式:封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作.

主要将数据结构与数据操作分离,解决数据结构和操作耦合性问题.

访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口

访问者模式的主要应用场景是:对咬对一个对象结构中的对象进行很多不同操作(这些操作没有关联关系),同时需要避免让这些操作污染这些对象的类,可以选用访问者模式解决

使用场景:

测评系统的需求

1.将观众分为男人和女人,对歌手进行评价,当看完某个歌手表演后,得到他们对该歌手的不同评价(评价有不同的种类,比如成功,失败等)

访问者模式原理类图:

1.Visitor是抽象访问者,为该对象结构中的ConcreteElement的每一个类声明一个visit操作

2.ConcreteVisitor:是一个具体的访问者,实现每个有Visitor声明的操作,是每个操作实现的部分.

3.ObjectStructure能枚举它的元素,可以提供一个高层接口,用来允许访问者访问元素

4.Element定义一个accept方法,接收一个访问者对象

5.ConcreteElement为具体元素,实现了accept方法.

uml类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design14;

//相当于访问者
public abstract class Action {
	
	//得到男性 的测评
	public abstract void getManResult(Man man);
	
	//得到女的 测评
	public abstract void getWomanResult(Woman woman);
}
package com.hjm.shd.shardingspheredemo.designPatterns.design14;

public class Success extends Action {

	@Override
	public void getManResult(Man man) {
		System.out.println(" 男人给的评价该歌手很成功 !");
	}

	@Override
	public void getWomanResult(Woman woman) {
		System.out.println(" 女人给的评价该歌手很成功 !");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design14;

public class Fail extends Action {

	@Override
	public void getManResult(Man man) {
		System.out.println(" 男人给的评价该歌手失败 !");
	}

	@Override
	public void getWomanResult(Woman woman) {
		System.out.println(" 女人给的评价该歌手失败 !");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design14;

public abstract class Person {
	
	//提供一个方法,让访问者可以访问
	public abstract void accept(Action action);
}
package com.hjm.shd.shardingspheredemo.designPatterns.design14;

public class Man extends Person {

	@Override
	public void accept(Action action) {
		action.getManResult(this);
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design14;

//说明
//1. 这里我们使用到了双分派, 即首先在客户端程序中,将具体状态作为参数传递Woman中(第一次分派)
//2. 然后Woman 类调用作为参数的 "具体方法" 中方法getWomanResult, 同时将自己(this)作为参数
//   传入,完成第二次的分派
public class Woman extends Person{

	@Override
	public void accept(Action action) {
		action.getWomanResult(this);
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design14;

import java.util.LinkedList;
import java.util.List;

//数据结构,管理很多人(Man , Woman)
public class ObjectStructure {

	//维护了一个集合
	private List<Person> persons = new LinkedList<>();
	
	//增加到list
	public void attach(Person p) {
		persons.add(p);
	}
	//移除
	public void detach(Person p) {
		persons.remove(p);
	}
	
	//显示测评情况
	public void display(Action action) {
		for(Person p: persons) {
			p.accept(action);
		}
	}
}

如果此时需要扩展一个wait状态,直接添加就行

package com.hjm.shd.shardingspheredemo.designPatterns.design14;

public class Wait extends Action {

	@Override
	public void getManResult(Man man) {
		System.out.println(" 男人给的评价是该歌手待定 ..");
	}

	@Override
	public void getWomanResult(Woman woman) {
		System.out.println(" 女人给的评价是该歌手待定 ..");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design14;

public class Client {

	public static void main(String[] args) {
		//创建ObjectStructure
		ObjectStructure objectStructure = new ObjectStructure();
		
		objectStructure.attach(new Man());
		objectStructure.attach(new Woman());
		
		
		//成功
		Success success = new Success();
		objectStructure.display(success);
		
		System.out.println("===============");
		Fail fail = new Fail();
		objectStructure.display(fail);
		
		System.out.println("=======给的是待定的测评========");
		
		Wait wait = new Wait();
		objectStructure.display(wait);
	}

}

双分派概念:

所谓双分派是指不管类怎么变化,我们都能找到期待的方法运行.双分派意味着得到执行的操作取决于请求的种类和两个接收者的类型.

假设我们需要添加一个wait的状态类,考察man和woman类的反应,由于使用了双分派,只需增加一个action子类即可在客户端调用,不需要改动任何其他类的代码.

访问者模式的优缺点:

优点:

1.访问者模式符合单一职责原则,让程序具有优秀的扩展性,灵活性非常高

2.访问者模式可以对功能进行统一,可以做报表,UI,拦截器与过滤器,适用于数据结构相对稳定的系统

缺点:

1.具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的,这样造成了具体元素变更比较困难.

2.违背了依赖倒置原则.访问者依赖的是具体元素,而不是抽象元素

3.如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式比较合适.

迭代器模式

迭代器模式指:如果我们的集合元素是用不同的方式实现的,如数组或者集合或者其他方式,当客户端要遍历这些集合元素时,就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决.

迭代器模式,提供一种遍历集合元素的统一接口,用一直的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露内部结构.

使用场景:

以组合模式中院系为例子,一个学校有多个院系,一个院系又有多个专业,不同院系采用的集合形式不同,例如一个院系用集合,一个院系用数组存储数据,当我们需要遍历两个院系的数据时,如何处理.

uml原理类图:

1.Iterator:迭代器接口,是系统提供的,含有hasNext  next  remove等方法

2.ConcreteIterator:具体的迭代器类,管理迭代

3.Aggregate:一个统一的聚合接口,将客户端和具体聚合解耦

4.ConcreteAggreage:具体的聚合持有对象集合,并提供一个方法,返回一个迭代器,该迭代器可以正确遍历集合

5.Client:客户端,通过Iterator和Aggregate 依赖子类.

案例uml类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design15;

//学院下面的系
public class Department {

	private String name;
	private String desc;
	public Department(String name, String desc) {
		super();
		this.name = name;
		this.desc = desc;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
	
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design15;

import java.util.Iterator;

//计算机学院迭代器
public class ComputerCollegeIterator implements Iterator {

	//这里我们需要Department 是以怎样的方式存放=>数组
	Department[] departments;
	int position = 0; //遍历的位置
	
	
	
	
	public ComputerCollegeIterator(Department[] departments) {
		this.departments = departments;
	}

	//判断是否还有下一个元素
	@Override
	public boolean hasNext() {
		if(position >= departments.length || departments[position] == null) {
			return false;
		}else {
		
			return true;
		}
	}

	@Override
	public Object next() {
		Department department = departments[position];
		position += 1;
		return department;
	}
	
	//删除的方法,默认空实现
	public void remove() {
		
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design15;

import java.util.Iterator;
import java.util.List;
//信息工程学院迭代器
public class InfoColleageIterator implements Iterator {

	
	List<Department> departmentList; // 信息工程学院是以List方式存放系
	int index = -1;//索引
	

	public InfoColleageIterator(List<Department> departmentList) {
		this.departmentList = departmentList;
	}

	//判断list中还有没有下一个元素
	@Override
	public boolean hasNext() {
		if(index >= departmentList.size() - 1) {
			return false;
		} else {
			index += 1;
			return true;
		}
	}

	@Override
	public Object next() {
		return departmentList.get(index);
	}
	
	//空实现remove
	public void remove() {
		
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design15;

import java.util.Iterator;

public interface College {
	
	public String getName();
	
	//增加系的方法
	public void addDepartment(String name, String desc);
	
	//返回一个迭代器,遍历
	public Iterator  createIterator();
}
package com.hjm.shd.shardingspheredemo.designPatterns.design15;

import java.util.Iterator;

public class ComputerCollege implements College {

	Department[] departments;
	int numOfDepartment = 0 ;// 保存当前数组的对象个数
	
	
	public ComputerCollege() {
		departments = new Department[5];
		addDepartment("Java专业", " Java专业 ");
		addDepartment("PHP专业", " PHP专业 ");
		addDepartment("大数据专业", " 大数据专业 ");
		
	}
	
	
	@Override
	public String getName() {
		return "计算机学院";
	}

	@Override
	public void addDepartment(String name, String desc) {
		Department department = new Department(name, desc);
		departments[numOfDepartment] = department;
		numOfDepartment += 1;
	}

	@Override
	public Iterator createIterator() {
		return new ComputerCollegeIterator(departments);
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design15;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class InfoCollege implements College {

	List<Department> departmentList;
	
	
	public InfoCollege() {
		departmentList = new ArrayList<Department>();
		addDepartment("信息安全专业", " 信息安全专业 ");
		addDepartment("网络安全专业", " 网络安全专业 ");
		addDepartment("服务器安全专业", " 服务器安全专业 ");
	}
	
	@Override
	public String getName() {
		return "信息工程学院";
	}

	@Override
	public void addDepartment(String name, String desc) {
		Department department = new Department(name, desc);
		departmentList.add(department);
	}

	@Override
	public Iterator createIterator() {
		return new InfoColleageIterator(departmentList);
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design15;

import java.util.Iterator;
import java.util.List;

public class OutPutImpl {
	
	//学院集合
	List<College> collegeList;

	public OutPutImpl(List<College> collegeList) {
		
		this.collegeList = collegeList;
	}
	//遍历所有学院,然后调用printDepartment 输出各个学院的系
	public void printCollege() {
		
		//从collegeList 取出所有学院, Java 中的 List 已经实现Iterator
		Iterator<College> iterator = collegeList.iterator();
		
		while(iterator.hasNext()) {
			//取出一个学院
			College college = iterator.next();
			System.out.println("=== "+college.getName() +"=====" );
			printDepartment(college.createIterator()); //得到对应迭代器
		}
	}
	
	
	//输出 学院输出 系
	
	public void printDepartment(Iterator iterator) {
		while(iterator.hasNext()) {
			Department d = (Department)iterator.next();
			System.out.println(d.getName());
		}
	}
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design15;

import java.util.ArrayList;
import java.util.List;

public class Client {

	public static void main(String[] args) {
		//创建学院
		List<College> collegeList = new ArrayList<College>();
		
		ComputerCollege computerCollege = new ComputerCollege();
		InfoCollege infoCollege = new InfoCollege();
		
		collegeList.add(computerCollege);
		//collegeList.add(infoCollege);
		
		OutPutImpl outPutImpl = new OutPutImpl(collegeList);
		outPutImpl.printCollege();
	}

}

迭代器模式在JDK-ArrayList集合应用源码分析:

package com.hjm.shd.shardingspheredemo.designPatterns.jdk;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorDemo {

	public static void main(String[] args) {

		List<String> a = new ArrayList<>();
		a.add("jack");// ..
		// 获取到迭代器
		Iterator Itr = a.iterator();
		while (Itr.hasNext()) {
			System.out.println(Itr.next());
		}
		
	

	}

}

源码uml类图:

1.内部类itr充当具体实现迭代器Iterator类, 作为ArrayList内部类.

2.List就是充当了聚合接口,含有一个iterator()方法,返回一个迭代器对象

3.ArrayList是实现聚合接口List的子类,实现了iterator()

4.Iterator接口系统提供

5.迭代器模式解决了不同集合(ArrayList, LinkedList) 统一遍历问题.

迭代器模式的优缺点:

优点:

1.提供了一个统一的方法遍历对象,客户端不用再考虑聚合的类型,使用一种方法就可以遍历对象了

2.隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成

3.提供了一种设计思想,就是一个雷应该只有一个引起变化的原因(单一职责),在聚合类中,我们吧迭代器分开,就是要把管理对象的集合和遍历对象的集合责任分开.

4.当要展示一组相似对象,或者遍历一组相同对象时使用,适合使用迭代器模式

缺点:

1.每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类.

观察者模式

观察者模式是一种行为型设计模式,定义了一种一对多的依赖关系.多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,会通知所有观察者对象并自动更新.观察者模式的核心是在主题对象和观察者对象之间简历松耦合关系,以便于主题对象状态改变时通知观察者对象做出响应的处理.

使用场景:

天气预报项目需求

1.气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或者第三方)

2.需要设计开放型API,便于其他第三方也能接入气象站获取数据.

3.提供温度,气压和湿度接口

4.测量数据更新时,要能实时的通知给第三方.

uml类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design16;

//观察者接口,有观察者来实现
public interface Observer {

	public void update(float temperature, float pressure, float humidity);
}
package com.hjm.shd.shardingspheredemo.designPatterns.design16;


//主题接口, 让WeatherData 来实现,里面包含注册观察者,清除观察者和通知所有观察者方法.
public interface Subject {
	
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObservers();
}
package com.hjm.shd.shardingspheredemo.designPatterns.design16;

import java.util.ArrayList;

/**
 * 类是核心
 * 1. 包含最新的天气情况信息 
 * 2. 含有 观察者集合,使用ArrayList管理
 * 3. 当数据有更新时,就主动的调用   ArrayList, 通知所有的(接入方)就看到最新的信息
 * @author Administrator
 *
 */
public class WeatherData implements Subject {
	private float temperatrue;
	private float pressure;
	private float humidity;
	//观察者集合
	private ArrayList<Observer> observers;
	
	//加入新的第三方

	public WeatherData() {
		observers = new ArrayList<Observer>();
	}

	public float getTemperature() {
		return temperatrue;
	}

	public float getPressure() {
		return pressure;
	}

	public float getHumidity() {
		return humidity;
	}

	public void dataChange() {
		//调用 接入方的 update
		
		notifyObservers();
	}

	//当数据有更新时,就调用 setData
	public void setData(float temperature, float pressure, float humidity) {
		this.temperatrue = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		//调用dataChange, 将最新的信息 推送给 接入方 currentConditions
		dataChange();
	}

	//注册一个观察者
	@Override
	public void registerObserver(Observer o) {
		observers.add(o);
	}

	//移除一个观察者
	@Override
	public void removeObserver(Observer o) {
		if(observers.contains(o)) {
			observers.remove(o);
		}
	}

	//遍历所有的观察者,并通知
	@Override
	public void notifyObservers() {
		for(int i = 0; i < observers.size(); i++) {
			observers.get(i).update(this.temperatrue, this.pressure, this.humidity);
		}
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design16;

public class BaiduSite implements Observer {

	// 温度,气压,湿度
	private float temperature;
	private float pressure;
	private float humidity;

	// 更新 天气情况,是由 WeatherData 来调用,我使用推送模式
	public void update(float temperature, float pressure, float humidity) {
		this.temperature = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		display();
	}

	// 显示
	public void display() {
		System.out.println("===百度网站====");
		System.out.println("***百度网站 气温 : " + temperature + "***");
		System.out.println("***百度网站 气压: " + pressure + "***");
		System.out.println("***百度网站 湿度: " + humidity + "***");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design16;

//具体观察者
public class CurrentConditions implements Observer {

	// 温度,气压,湿度
	private float temperature;
	private float pressure;
	private float humidity;

	// 更新 天气情况,是由 WeatherData 来调用,我使用推送模式
	public void update(float temperature, float pressure, float humidity) {
		this.temperature = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		display();
	}

	// 显示
	public void display() {
		System.out.println("***Today mTemperature: " + temperature + "***");
		System.out.println("***Today mPressure: " + pressure + "***");
		System.out.println("***Today mHumidity: " + humidity + "***");
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design16;

public class Client {

	public static void main(String[] args) {
		//创建一个WeatherData
		WeatherData weatherData = new WeatherData();
		
		//创建观察者
		CurrentConditions currentConditions = new CurrentConditions();
		BaiduSite baiduSite = new BaiduSite();
		
		//注册到weatherData
		weatherData.registerObserver(currentConditions);
		weatherData.registerObserver(baiduSite);
		
		//测试
		System.out.println("通知各个注册的观察者, 看看信息");
		weatherData.setData(10f, 100f, 30.3f);
		
		
		weatherData.removeObserver(currentConditions);
		//测试
		System.out.println("通知各个注册的观察者, 看看信息");
		weatherData.setData(10f, 100f, 30.3f);
	}

}

观察者模式在JDK源码分析:

1.Observable 的作用和地位等价于 我们前面讲过的Subject

2.Observable 是类,不是接口,类中已经实现了核心方法,即管理Observer的方法,add  delete notify   

3.Observer 的作用和地位等价于我们前面讲过的Observer , 有update

4.Observable  和 Observer 的使用方法和我们前面讲过的一样, 只是Observable 是类, 通过继承来实现观察者模式.

中介者模式

中介者模式:用一个中介对象来封装一系列的对象交互.中介者使各个对象不需要显示的相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互.中介者模式使代码易于维护.

例如:springMVC

使用场景:

智能家庭项目:

1.智能家庭包括各种设备,闹钟,咖啡机,电视机,窗帘等.

2.主人要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,比如流程为,闹铃响起->咖啡机开始做咖啡->窗帘自动落下->电视机开始播放等.

中介者模式uml类图:

代码uml类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design17;

//同事抽象类
public abstract class Colleague {
	private Mediator mediator;
	public String name;

	public Colleague(Mediator mediator, String name) {

		this.mediator = mediator;
		this.name = name;

	}

	public Mediator GetMediator() {
		return this.mediator;
	}

	public abstract void SendMessage(int stateChange);
}
package com.hjm.shd.shardingspheredemo.designPatterns.design17;

public abstract class Mediator {
	//将给中介者对象,加入到集合中
	public abstract void Register(String colleagueName, Colleague colleague);

	//接收消息, 具体的同事对象发出
	public abstract void GetMessage(int stateChange, String colleagueName);

	public abstract void SendMessage();
}
package com.hjm.shd.shardingspheredemo.designPatterns.design17;

//具体的同事类(闹钟)
public class Alarm extends Colleague {

	//构造器
	public Alarm(Mediator mediator, String name) {
		super(mediator, name);
		//在创建Alarm 同事对象时,将自己放入到ConcreteMediator 对象中[集合]
		mediator.Register(name, this);
	}

	public void SendAlarm(int stateChange) {
		SendMessage(stateChange);
	}

	@Override
	public void SendMessage(int stateChange) {
		//调用的中介者对象的getMessage
		this.GetMediator().GetMessage(stateChange, this.name);
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design17;

//具体同事类(咖啡机)
public class CoffeeMachine extends Colleague {

	public CoffeeMachine(Mediator mediator, String name) {
		super(mediator, name);
		mediator.Register(name, this);
	}

	@Override
	public void SendMessage(int stateChange) {
		this.GetMediator().GetMessage(stateChange, this.name);
	}

	public void StartCoffee() {
		System.out.println("It's time to startcoffee!");
	}

	public void FinishCoffee() {

		System.out.println("After 5 minutes!");
		System.out.println("Coffee is ok!");
		SendMessage(0);
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design17;

//具体同事类(窗帘)
public class Curtains extends Colleague {

	public Curtains(Mediator mediator, String name) {
		super(mediator, name);
		mediator.Register(name, this);
	}

	@Override
	public void SendMessage(int stateChange) {
		this.GetMediator().GetMessage(stateChange, this.name);
	}

	public void UpCurtains() {
		System.out.println("I am holding Up Curtains!");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design17;

//具体同事类
public class TV extends Colleague {

	public TV(Mediator mediator, String name) {
		super(mediator, name);
		mediator.Register(name, this);
	}

	@Override
	public void SendMessage(int stateChange) {
		this.GetMediator().GetMessage(stateChange, this.name);
	}

	public void StartTv() {
		System.out.println("It's time to StartTv!");
	}

	public void StopTv() {
		System.out.println("StopTv!");
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design17;

import java.util.HashMap;

//具体的中介者类
public class ConcreteMediator extends Mediator {
	//集合,放入所有的同事对象
	private HashMap<String, Colleague> colleagueMap;
	private HashMap<String, String> interMap;

	public ConcreteMediator() {
		colleagueMap = new HashMap<String, Colleague>();
		interMap = new HashMap<String, String>();
	}

	@Override
	public void Register(String colleagueName, Colleague colleague) {
		colleagueMap.put(colleagueName, colleague);

		if (colleague instanceof Alarm) {
			interMap.put("Alarm", colleagueName);
		} else if (colleague instanceof CoffeeMachine) {
			interMap.put("CoffeeMachine", colleagueName);
		} else if (colleague instanceof TV) {
			interMap.put("TV", colleagueName);
		} else if (colleague instanceof Curtains) {
			interMap.put("Curtains", colleagueName);
		}

	}

	//具体中介者的核心方法
	//1. 根据得到消息,完成对应任务
	//2. 中介者在这个方法,协调各个具体的同事对象,完成任务
	@Override
	public void GetMessage(int stateChange, String colleagueName) {

		//处理闹钟发出的消息
		if (colleagueMap.get(colleagueName) instanceof Alarm) {
			if (stateChange == 0) {
				((CoffeeMachine) (colleagueMap.get(interMap
						.get("CoffeeMachine")))).StartCoffee();
				((TV) (colleagueMap.get(interMap.get("TV")))).StartTv();
			} else if (stateChange == 1) {
				((TV) (colleagueMap.get(interMap.get("TV")))).StopTv();
			}

		} else if (colleagueMap.get(colleagueName) instanceof CoffeeMachine) {
			((Curtains) (colleagueMap.get(interMap.get("Curtains"))))
					.UpCurtains();

		} else if (colleagueMap.get(colleagueName) instanceof TV) {//如果TV发现消息

		} else if (colleagueMap.get(colleagueName) instanceof Curtains) {
			//如果是以窗帘发出的消息,这里处理...
		}

	}

	@Override
	public void SendMessage() {

	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design17;

public class ClientTest {

	public static void main(String[] args) {
		//创建一个中介者对象
		Mediator mediator = new ConcreteMediator();
		
		//创建Alarm 并且加入到  ConcreteMediator 对象的HashMap
		Alarm alarm = new Alarm(mediator, "alarm");
		
		//创建了CoffeeMachine 对象,并  且加入到  ConcreteMediator 对象的HashMap
		CoffeeMachine coffeeMachine = new CoffeeMachine(mediator, "coffeeMachine");
		
		//创建 Curtains , 并  且加入到  ConcreteMediator 对象的HashMap
		Curtains curtains = new Curtains(mediator, "curtains");
		TV tV = new TV(mediator, "TV");
		
		//让闹钟发出消息
		alarm.SendAlarm(0);
		coffeeMachine.FinishCoffee();
		alarm.SendAlarm(1);
	}

}

中介者模式的优缺点:

1.多个类相互耦合,会形成网状结构,使用中介者模式将网状结构分离为星型结构,进行解耦

2.减少类间依赖,降低了耦合,符合迪米特法则

3.中介者承担了较多的责任,一旦中介者出现了问题,整个系统会收到影响.

4.如果设计不当,中介者对象本身变得过于复杂,这点在实际使用时,需要特别注意.

备忘录模式

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将对象恢复到原先保存的状态.

使用场景:

游戏角色状态恢复问题

游戏角色有攻击力和防御力,在大战boss前保存自身的状态(攻击力和防御力),当大战boss后被boss技能打中,攻击力和防御力下降,打完boss后,从备忘录将对象的状态恢复到大战前的状态.

备忘录模式原理类图:

1.originator:对象(需要保存状态的对象)

2.Memento:备忘录对象,负责保存好记录,即Originator内部状态.

3.Caretaker:守护者对象,负责保存多个备忘录对象,使用集合管理,提高效率.

4.说明:如果希望保存多个originator对象的不同时间的状态,也可,只需要HashMap<String,集合>

原理图代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design18.thread;

//备忘录对象
public class Memento {
	private String state;

	//构造器
	public Memento(String state) {
		super();
		this.state = state;
	}

	public String getState() {
		return state;
	}
	
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design18.thread;

//需要保存状态的对象
public class Originator {

	private String state;//状态信息

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
	
	//编写一个方法,可以保存一个状态对象 Memento
	//因此编写一个方法,返回 Memento
	public Memento saveStateMemento() {
		return new Memento(state);
	}
	
	//通过备忘录对象,恢复状态
	public void getStateFromMemento(Memento memento) {
		state = memento.getState();
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design18.thread;

import java.util.ArrayList;
import java.util.List;

//守护者对象
public class Caretaker {
	
	//在List 集合中会有很多的备忘录对象
	private List<Memento> mementoList = new ArrayList<Memento>();
	
	public void add(Memento memento) {
		mementoList.add(memento);
	}
	
	//获取到第index个Originator 的 备忘录对象(即保存状态)
	public Memento get(int index) {
		return mementoList.get(index);
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design18.thread;

import java.util.ArrayList;
import java.util.HashMap;

public class Client {

	public static void main(String[] args) {
		
		Originator originator = new Originator();
		Caretaker caretaker = new Caretaker();
		
		originator.setState(" 状态#1 攻击力 100 ");
		
		//保存了当前的状态
		caretaker.add(originator.saveStateMemento());
		
		originator.setState(" 状态#2 攻击力 80 ");
		
		caretaker.add(originator.saveStateMemento());
		
		originator.setState(" 状态#3 攻击力 50 ");
		caretaker.add(originator.saveStateMemento());
		
		
		
		System.out.println("当前的状态是 =" + originator.getState());
		
		//希望得到状态 1, 将 originator 恢复到状态1
		
		originator.getStateFromMemento(caretaker.get(0));
		System.out.println("恢复到状态1 , 当前的状态是");
		System.out.println("当前的状态是 =" + originator.getState());
		
		
		
	}

}

需求类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design18.game;

//备忘录对象
public class Memento {

	//攻击力
	private int vit;
	//防御力
	private int def;
	public Memento(int vit, int def) {
		super();
		this.vit = vit;
		this.def = def;
	}
	public int getVit() {
		return vit;
	}
	public void setVit(int vit) {
		this.vit = vit;
	}
	public int getDef() {
		return def;
	}
	public void setDef(int def) {
		this.def = def;
	}
	
	
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design18.game;

//游戏角色
public class GameRole {

	private int vit;
	private int def;
	
	//创建Memento ,即根据当前的状态得到Memento
	public Memento createMemento() {
		return new Memento(vit, def);
	}
	
	//从备忘录对象,恢复GameRole的状态
	public void recoverGameRoleFromMemento(Memento memento) {
		this.vit = memento.getVit();
		this.def = memento.getDef();
	}
	
	//显示当前游戏角色的状态
	public void display() {
		System.out.println("游戏角色当前的攻击力:" + this.vit + " 防御力: " + this.def);
	}

	public int getVit() {
		return vit;
	}

	public void setVit(int vit) {
		this.vit = vit;
	}

	public int getDef() {
		return def;
	}

	public void setDef(int def) {
		this.def = def;
	}
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design18.game;

import java.util.ArrayList;
import java.util.HashMap;

//守护者对象, 保存游戏角色的状态
public class Caretaker {

	//如果只保存一次状态
	private Memento  memento;
	//对GameRole 保存多次状态
	//private ArrayList<Memento> mementos;
	//对多个游戏角色保存多个状态
	//private HashMap<String, ArrayList<Memento>> rolesMementos;

	public Memento getMemento() {
		return memento;
	}

	public void setMemento(Memento memento) {
		this.memento = memento;
	}
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design18.game;

public class Client {

	public static void main(String[] args) {
		//创建游戏角色
		GameRole gameRole = new GameRole();
		gameRole.setVit(100);
		gameRole.setDef(100);
		
		System.out.println("和boss大战前的状态");
		gameRole.display();
		
		//把当前状态保存caretaker
		Caretaker caretaker = new Caretaker();
		caretaker.setMemento(gameRole.createMemento());
		
		System.out.println("和boss大战~~~");
		gameRole.setDef(30);
		gameRole.setVit(30);
		
		gameRole.display();
		
		System.out.println("大战后,使用备忘录对象恢复到战前");
		
		gameRole.recoverGameRoleFromMemento(caretaker.getMemento());
		System.out.println("恢复后的状态");
		gameRole.display();
	}

}

备忘录模式的优缺点:

1.给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便的回到某个历史状态

2.实现了信息封装,使得用户不需要关心状态的保存细节

3.如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会小号一定的内存,这个需要注意

4.为了节约内存,备忘录模式可以和原型模式配合使用.

适用场景:

1.后悔药

2.打游戏时的存档.

3.Windows里的 ctrl + z

4.IE中的后退

5.数据库事务管理

解释器模式

解释器模式是指:给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的句子(表达式)

应用可以将一个需要解释器执行的语言中的句子表示为一个抽象语法树,一些重复出现的问题可以用一种简单的语言来表达,一个简单语法需要解释的场景.

这样的例子还有,编译器,运算表达式计算,正则表达式,机器人等.

使用场景:

通过解释器模式来实现四则运算,如计算a+b-c的值,具体要求

1.先输入表达式的形式,比如a+b+c-d+e,要求表达式的字母不能重复

2.在分别输入a,b,c,d,e的值

3.最后求出结果.

原理类图:

1.Context:是环境角色,含有解释器之外的全局信息.

2.AbstractExpression:为抽象表达式,声明一个抽象的解释器操作,这个方法为抽象语法树中所有的节点所共享.

3.TerminalExpression:为终结符表达式,实现与文法中的终结符相关的解释器操作

4.NonTermialExpression:为非终结符表达式,为文法中的非终结符实现解释操作.

5.说明:输入context 和 TerminalExpression 信息通过 Client 输入即可.

案例类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design19;

import java.util.HashMap;

/**
 * 抽象类表达式,通过HashMap 键值对, 可以获取到变量的值
 * 
 * @author Administrator
 *
 */
public abstract class Expression {
	// a + b - c
	// 解释公式和数值, key 就是公式(表达式) 参数[a,b,c], value就是就是具体值
	// HashMap {a=10, b=20}
	public abstract int interpreter(HashMap<String, Integer> var);
}
package com.hjm.shd.shardingspheredemo.designPatterns.design19;

import java.util.HashMap;


/**
 * 变量的解释器
 * @author Administrator
 *
 */
public class VarExpression extends Expression {

	private String key; // key=a,key=b,key=c

	public VarExpression(String key) {
		this.key = key;
	}

	// var 就是{a=10, b=20}
	// interpreter 根据 变量名称,返回对应值
	@Override
	public int interpreter(HashMap<String, Integer> var) {
		return var.get(this.key);
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design19;

import java.util.HashMap;

/**
 * 抽象运算符号解析器 这里,每个运算符号,都只和自己左右两个数字有关系,
 * 但左右两个数字有可能也是一个解析的结果,无论何种类型,都是Expression类的实现类
 * 
 * @author Administrator
 *
 */
public class SymbolExpression extends Expression {

	protected Expression left;
	protected Expression right;

	public SymbolExpression(Expression left, Expression right) {
		this.left = left;
		this.right = right;
	}

	//因为 SymbolExpression 是让其子类来实现,因此 interpreter 是一个默认实现
	@Override
	public int interpreter(HashMap<String, Integer> var) {
		return 0;
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design19;

import java.util.HashMap;

/**
 * 加法解释器
 * @author Administrator
 *
 */
public class AddExpression extends SymbolExpression  {

	public AddExpression(Expression left, Expression right) {
		super(left, right);
	}

	//处理相加
	//var 仍然是 {a=10,b=20}..
	//一会我们debug 源码,就ok
	public int interpreter(HashMap<String, Integer> var) {
		//super.left.interpreter(var) : 返回 left 表达式对应的值 a = 10
		//super.right.interpreter(var): 返回right 表达式对应值 b = 20
		return super.left.interpreter(var) + super.right.interpreter(var);
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design19;

import java.util.HashMap;

public class SubExpression extends SymbolExpression {

	public SubExpression(Expression left, Expression right) {
		super(left, right);
	}

	//求出left 和 right 表达式相减后的结果
	public int interpreter(HashMap<String, Integer> var) {
		return super.left.interpreter(var) - super.right.interpreter(var);
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design19;

import java.util.HashMap;
import java.util.Stack;

//表达式计算器类
public class Calculator {

	// 定义表达式
	private Expression expression;

	// 构造函数传参,并解析
	public Calculator(String expStr) { // expStr = a+b
		// 安排运算先后顺序 通过栈(stack:先进后出) 堆Heap
		Stack<Expression> stack = new Stack<>();
		// 表达式拆分成字符数组 
		char[] charArray = expStr.toCharArray();// [a, +, b]

		Expression left = null;
		Expression right = null;
		//遍历我们的字符数组, 即遍历  [a, +, b]
		//针对不同的情况,做处理
		for (int i = 0; i < charArray.length; i++) {
			switch (charArray[i]) {
			case '+': //
				left = stack.pop();// 从stack取出left => "a"
				right = new VarExpression(String.valueOf(charArray[++i]));// 取出右表达式 "b"
				stack.push(new AddExpression(left, right));// 然后根据得到left 和 right 构建 AddExpresson加入stack
				break;
			case '-': // 
				left = stack.pop();
				right = new VarExpression(String.valueOf(charArray[++i]));
				stack.push(new SubExpression(left, right));
				break;
			default: 
				//如果是一个 Var 就创建要给 VarExpression 对象,并push到 stack
				stack.push(new VarExpression(String.valueOf(charArray[i])));
				break;
			}
		}
		//当遍历完整个 charArray 数组后,stack 就得到最后Expression
		this.expression = stack.pop();
	}

	public int run(HashMap<String, Integer> var) {
		//最后将表达式a+b和 var = {a=10,b=20}
		//然后传递给expression的interpreter进行解释执行
		return this.expression.interpreter(var);
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design19;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

public class ClientTest {

	public static void main(String[] args) throws IOException {
		String expStr = getExpStr(); // a+b
		HashMap<String, Integer> var = getValue(expStr);// var {a=10, b=20}
		Calculator calculator = new Calculator(expStr);
		System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
	}

	// 获得表达式
	public static String getExpStr() throws IOException {
		System.out.print("请输入表达式:");
		return (new BufferedReader(new InputStreamReader(System.in))).readLine();
	}

	// 获得值映射
	public static HashMap<String, Integer> getValue(String expStr) throws IOException {
		HashMap<String, Integer> map = new HashMap<>();

		for (char ch : expStr.toCharArray()) {
			if (ch != '+' && ch != '-') {
				if (!map.containsKey(String.valueOf(ch))) {
					System.out.print("请输入" + String.valueOf(ch) + "的值:");
					String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
					map.put(String.valueOf(ch), Integer.valueOf(in));
				}
			}
		}

		return map;
	}
}

解释器模式在Spring框架源码分析:

public static void main(String[] args) {
		//创建一个 Parser 对象
		SpelExpressionParser parser = new SpelExpressionParser();
		//
		//通过 Parser 对象 获取到一个Expression对象
		//会根据不同的  Parser 对象 ,返回不同的 Expression对象
		Expression expression = parser.parseExpression("10 * (2 + 1) * 1 + 66"); //96
		int result = (Integer) expression.getValue();
		System.out.println(result);

	}

1.Expression 接口 表达式接口 下面有不同的实现类,比如 SpelException 或者 CompositeStringExpression 使用的时候,根据你创建的不同的Parser对象,返回不同的Expression对象

2.

public Expression parseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
   if (context != null && context.isTemplate()) {
      return parseTemplate(expressionString, context);//返回CompositeStringExpression
   }
   else {
      return doParseExpression(expressionString, context);//返回SpelException
   }
}

3.使用符合的Expression对象,调用getValue解释执行表达式,最后得到结果。

解释器模式的优缺点:

1.当有一个语言需要解释执行,可以将该语言中的句子表示为一个抽象语法树,就可以考虑使用解释器模式,让程序具有良好的扩展性。

2.使用解释器可能带来的问题:解释器模式会引起类膨胀,解释器模式采用递归调用方法,将会导致调式非常复杂,效率可能降低。

应用场景:

编译器   运算表达式计算   正则表达式  机器人等。

状态模式

状态模式:它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换。

当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。

使用场景:

app抽奖问题

状态模式原理类图:

1.Context 类为环境角色,用于维护State实例,这个实例定义当前状态。

2.State 是抽象状态角色,定义一个接口封装与Context 的一个特点接口相关行为。

3.ConcreteState 具体的状态角色,每个子类实现一个与Context的一个状态相关行为。

代码uml类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design20;

/**
 * 状态抽象类
 * @author Administrator
 *
 */
public abstract class State {

	
	// 扣除积分 - 50
    public abstract void deductMoney();

    // 是否抽中奖品
    public abstract boolean raffle();

    // 发放奖品
    public abstract  void dispensePrize();

}
package com.hjm.shd.shardingspheredemo.designPatterns.design20;

/**
 * 不能抽奖状态
 * @author Administrator
 *
 */
public class NoRaffleState extends State {

	 // 初始化时传入活动引用,扣除积分后改变其状态
    RaffleActivity activity;

    public NoRaffleState(RaffleActivity activity) {
        this.activity = activity;
    }

    // 当前状态可以扣积分 , 扣除后,将状态设置成可以抽奖状态
    @Override
    public void deductMoney() {
        System.out.println("扣除50积分成功,您可以抽奖了");
        activity.setState(activity.getCanRaffleState());
    }

    // 当前状态不能抽奖
    @Override
    public boolean raffle() {
        System.out.println("扣了积分才能抽奖喔!");
        return false;
    }

    // 当前状态不能发奖品
    @Override
    public void dispensePrize() {
        System.out.println("不能发放奖品");
    }
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20;

import java.util.Random;

/**
 * 可以抽奖的状态
 * @author Administrator
 *
 */
public class CanRaffleState extends State {

    RaffleActivity activity;

    public CanRaffleState(RaffleActivity activity) {
        this.activity = activity;
    }

    //已经扣除了积分,不能再扣
    @Override
    public void deductMoney() {
        System.out.println("已经扣取过了积分");
    }

    //可以抽奖, 抽完奖后,根据实际情况,改成新的状态
    @Override
    public boolean raffle() {
        System.out.println("正在抽奖,请稍等!");
        Random r = new Random();
        int num = r.nextInt(10);
        // 10%中奖机会
        if(num == 0){
            // 改变活动状态为发放奖品 context
            activity.setState(activity.getDispenseState());
            return true;
        }else{
            System.out.println("很遗憾没有抽中奖品!");
            // 改变状态为不能抽奖
            activity.setState(activity.getNoRafflleState());
            return false;
        }
    }

    // 不能发放奖品
    @Override
    public void dispensePrize() {
        System.out.println("没中奖,不能发放奖品");
    }
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20;

/**
 * 发放奖品的状态
 * @author Administrator
 *
 */
public class DispenseState extends State {

	 // 初始化时传入活动引用,发放奖品后改变其状态
    RaffleActivity activity;

    public DispenseState(RaffleActivity activity) {
        this.activity = activity;
    }


    @Override
    public void deductMoney() {
        System.out.println("不能扣除积分");
    }

    @Override
    public boolean raffle() {
        System.out.println("不能抽奖");
        return false;
    }

    //发放奖品
    @Override
    public void dispensePrize() {
        if(activity.getCount() > 0){
            System.out.println("恭喜中奖了");
            // 改变状态为不能抽奖
            activity.setState(activity.getNoRafflleState());
        }else{
            System.out.println("很遗憾,奖品发送完了");
            // 改变状态为奖品发送完毕, 后面我们就不可以抽奖
            activity.setState(activity.getDispensOutState());
            //System.out.println("抽奖活动结束");
//            System.exit(0);
        }

    }
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20;

/**
 * 奖品发放完毕状态
 * 说明,当我们activity 改变成 DispenseOutState, 抽奖活动结束
 * @author Administrator
 *
 */
public class DispenseOutState extends State {

	// 初始化时传入活动引用
    RaffleActivity activity;

    public DispenseOutState(RaffleActivity activity) {
        this.activity = activity;
    }
    @Override
    public void deductMoney() {
        System.out.println("奖品发送完了,请下次再参加");
    }

    @Override
    public boolean raffle() {
        System.out.println("奖品发送完了,请下次再参加");
        return false;
    }

    @Override
    public void dispensePrize() {
        System.out.println("奖品发送完了,请下次再参加");
    }
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20;

/**
 * 抽奖活动 //
 * 
 * @author Administrator
 *
 */
public class RaffleActivity {

	// state 表示活动当前的状态,是变化
    State state = null;
    // 奖品数量
    int count = 0;
    
    // 四个属性,表示四种状态
    State noRafflleState = new NoRaffleState(this);
    State canRaffleState = new CanRaffleState(this);
    
    State dispenseState =   new DispenseState(this);
    State dispensOutState = new DispenseOutState(this);

    //构造器
    //1. 初始化当前的状态为 noRafflleState(即不能抽奖的状态)
    //2. 初始化奖品的数量 
    public RaffleActivity( int count) {
        this.state = getNoRafflleState();
        this.count = count;
    }

    //扣分, 调用当前状态的 deductMoney
    public void debuctMoney(){
        state.deductMoney();
    }

    //抽奖 
    public void raffle(){
    	// 如果当前的状态是抽奖成功
        if(state.raffle()){
        	//领取奖品
            state.dispensePrize();
        }

    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    //这里请大家注意,每领取一次奖品,count--
    public int getCount() {
    	int curCount = count; 
    	count--;
        return curCount;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public State getNoRafflleState() {
        return noRafflleState;
    }

    public void setNoRafflleState(State noRafflleState) {
        this.noRafflleState = noRafflleState;
    }

    public State getCanRaffleState() {
        return canRaffleState;
    }

    public void setCanRaffleState(State canRaffleState) {
        this.canRaffleState = canRaffleState;
    }

    public State getDispenseState() {
        return dispenseState;
    }

    public void setDispenseState(State dispenseState) {
        this.dispenseState = dispenseState;
    }

    public State getDispensOutState() {
        return dispensOutState;
    }

    public void setDispensOutState(State dispensOutState) {
        this.dispensOutState = dispensOutState;
    }
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20;

/**
 * 状态模式测试类
 * @author Administrator
 *
 */
public class ClientTest {

	public static void main(String[] args) {
		// 创建活动对象,奖品有1个奖品
        RaffleActivity activity = new RaffleActivity(1);

        // 我们连续抽30次奖
        for (int i = 0; i < 30; i++) {
            System.out.println("--------第" + (i + 1) + "次抽奖----------");
            // 参加抽奖,第一步点击扣除积分
            activity.debuctMoney();

            // 第二步抽奖
            activity.raffle();
        }
	}

}

状态模式在借贷平台源码分析:

项目需求:

订单流程的状态图:

订单状态横纵坐标关系图:

根据需求画出的订单uml类图:

代码分析:

package com.hjm.shd.shardingspheredemo.designPatterns.design20.money;

public abstract class AbstractState implements State {

	protected static final RuntimeException EXCEPTION = new RuntimeException("操作流程不允许");

	//抽象类,默认实现了 State 接口的所有方法
	//该类的所有方法,其子类(具体的状态类),可以有选择的进行重写
	
    @Override
    public void checkEvent(Context context) {
        throw EXCEPTION;
    }

    @Override
    public void checkFailEvent(Context context) {
        throw EXCEPTION;
    }

    @Override
    public void makePriceEvent(Context context) {
        throw EXCEPTION;
    }

    @Override
    public void acceptOrderEvent(Context context) {
        throw EXCEPTION;
    }

    @Override
    public void notPeopleAcceptEvent(Context context) {
        throw EXCEPTION;
    }

    @Override
    public void payOrderEvent(Context context) {
        throw EXCEPTION;
    }

    @Override
    public void orderFailureEvent(Context context) {
        throw EXCEPTION;
    }

    @Override
    public void feedBackEvent(Context context) {
        throw EXCEPTION;
    }
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20.money;

//各种具体状态类
class FeedBackState extends AbstractState {

	@Override
	public String getCurrentState() {
		return StateEnum.FEED_BACKED.getValue();
	}
}

class GenerateState extends AbstractState {

	@Override
	public void checkEvent(Context context) {
		context.setState(new ReviewState());
	}

	@Override
	public void checkFailEvent(Context context) {
		context.setState(new FeedBackState());
	}

	@Override
	public String getCurrentState() {
		return StateEnum.GENERATE.getValue();
	}
}

class NotPayState extends AbstractState {

	@Override
	public void payOrderEvent(Context context) {
		context.setState(new PaidState());
	}

	@Override
	public void feedBackEvent(Context context) {
		context.setState(new FeedBackState());
	}

	@Override
	public String getCurrentState() {
		return StateEnum.NOT_PAY.getValue();
	}
}

class PaidState extends AbstractState {

	@Override
	public void feedBackEvent(Context context) {
		context.setState(new FeedBackState());
	}

	@Override
	public String getCurrentState() {
		return StateEnum.PAID.getValue();
	}
}

class PublishState extends AbstractState {

	@Override
	public void acceptOrderEvent(Context context) {
		//把当前状态设置为  NotPayState。。。
		//至于应该变成哪个状态,有流程图来决定
		context.setState(new NotPayState());
	}

	@Override
	public void notPeopleAcceptEvent(Context context) {
		context.setState(new FeedBackState());
	}

	@Override
	public String getCurrentState() {
		return StateEnum.PUBLISHED.getValue();
	}
}

class ReviewState extends AbstractState {

	@Override
	public void makePriceEvent(Context context) {
		context.setState(new PublishState());
	}

	@Override
	public String getCurrentState() {
		return StateEnum.REVIEWED.getValue();
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design20.money;

/**
 * 状态接口
 * @author Administrator
 *
 */
public interface State {

	/**
     * 电审
     */
    void checkEvent(Context context);

    /**
     * 电审失败
     */
    void checkFailEvent(Context context);

    /**
     * 定价发布
     */
    void makePriceEvent(Context context);

    /**
     * 接单
     */
    void acceptOrderEvent(Context context);

    /**
     * 无人接单失效
     */
    void notPeopleAcceptEvent(Context context);

    /**
     * 付款
     */
    void payOrderEvent(Context context);

    /**
     * 接单有人支付失效
     */
    void orderFailureEvent(Context context);

    /**
     * 反馈
     */
    void feedBackEvent(Context context);


    String getCurrentState();
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20.money;

/**
 * 状态枚举类
 * @author Administrator
 *
 */
public enum StateEnum {

	 //订单生成
    GENERATE(1, "GENERATE"),

    //已审核
    REVIEWED(2, "REVIEWED"),

    //已发布
    PUBLISHED(3, "PUBLISHED"),

    //待付款
    NOT_PAY(4, "NOT_PAY"),

    //已付款
    PAID(5, "PAID"),

    //已完结
    FEED_BACKED(6, "FEED_BACKED");

    private int key;
    private String value;

    StateEnum(int key, String value) {
        this.key = key;
        this.value = value;
    }
    public int getKey() {return key;}
    public String getValue() {return value;}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20.money;

//环境上下文
public class Context extends AbstractState{
	//当前的状态 state, 根据我们的业务流程处理,不停的变化
	private State state;

    @Override
    public void checkEvent(Context context) {
        state.checkEvent(this);
        getCurrentState();
    }

    @Override
    public void checkFailEvent(Context context) {
        state.checkFailEvent(this);
        getCurrentState();
    }

    @Override
    public void makePriceEvent(Context context) {
        state.makePriceEvent(this);
        getCurrentState();
    }

    @Override
    public void acceptOrderEvent(Context context) {
        state.acceptOrderEvent(this);
        getCurrentState();
    }

    @Override
    public void notPeopleAcceptEvent(Context context) {
        state.notPeopleAcceptEvent(this);
        getCurrentState();
    }

    @Override
    public void payOrderEvent(Context context) {
        state.payOrderEvent(this);
        getCurrentState();
    }

    @Override
    public void orderFailureEvent(Context context) {
        state.orderFailureEvent(this);
        getCurrentState();
    }

    @Override
    public void feedBackEvent(Context context) {
        state.feedBackEvent(this);
        getCurrentState();
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    @Override
    public String getCurrentState() {
        System.out.println("当前状态 : " + state.getCurrentState());
        return state.getCurrentState();
    }
}
package com.hjm.shd.shardingspheredemo.designPatterns.design20.money;

/**测试类*/
public class ClientTest {

	public static void main(String[] args) {
		//创建context 对象
		Context context = new Context();
        //将当前状态设置为 PublishState
		context.setState(new PublishState());
        System.out.println(context.getCurrentState());
        
//        //publish --> not pay
        context.acceptOrderEvent(context);
//        //not pay --> paid
        context.payOrderEvent(context);
//        // 失败, 检测失败时,会抛出异常
//        try {
//        	context.checkFailEvent(context);
//        	System.out.println("流程正常..");
//		} catch (Exception e) {
//			// TODO: handle exception
//			System.out.println(e.getMessage());
//		}
        
	}

}

状态模式的优缺点:

1.代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中

2.方便维护,删除了容易出现的if-else语句

3.符合开闭原则

4.应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候,可以考虑使用状态模式。

策略模式

策略模式:定义算法族,分别分装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

这算法体现了几个设计原则  ,第一把变化的代码从不变的代码中分离出来;第二针对接口编程而不是具体类(定义了策略接口);第三,多用组合/聚合,少用继承(客户通过组合方式使用策略)

使用场景:

编写鸭子项目,具体要求如下:

1.有各种鸭子(比如:野鸭,北京鸭,水鸭,玩具鸭等,鸭子有各种行为,比如:叫,飞行,游泳等)

2.显示鸭子的信息

原理类图:

从上图可以看到,客户context有成员变量strategy或者其他的策略接口,至于需要使用到哪个策略,我们可以在构造器中指定。

鸭子场景uml类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design21;

public interface FlyBehavior {
	
	void fly(); // 子类具体实现
}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

public interface QuackBehavior {
	void quack();//子类实现
}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

public class BadFlyBehavior implements FlyBehavior {

	@Override
	public void fly() {
		System.out.println(" 飞翔技术一般 ");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

public class GoodFlyBehavior implements FlyBehavior {

	@Override
	public void fly() {
		System.out.println(" 飞翔技术高超 ~~~");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

public class NoFlyBehavior implements FlyBehavior{

	@Override
	public void fly() {
		System.out.println(" 不会飞翔  ");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

public abstract class Duck {

	//属性, 策略接口
	FlyBehavior flyBehavior;
	//其它属性<->策略接口
	QuackBehavior quackBehavior;
	
	public Duck() {
	
	}

	public abstract void display();//显示鸭子信息
	
	public void quack() {
		System.out.println("鸭子嘎嘎叫~~");
	}
	
	public void swim() {
		System.out.println("鸭子会游泳~~");
	}
	
	public void fly() {
		
		//改进
		if(flyBehavior != null) {
			flyBehavior.fly();
		}
	}

	public void setFlyBehavior(FlyBehavior flyBehavior) {
		this.flyBehavior = flyBehavior;
	}
	
	
	public void setQuackBehavior(QuackBehavior quackBehavior) {
		this.quackBehavior = quackBehavior;
	}
	
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

//北京鸭
public class PekingDuck extends Duck {

	
	//假如北京鸭可以飞翔,但是飞翔技术一般
	public PekingDuck() {
		flyBehavior = new BadFlyBehavior();
		
	}
	
	@Override
	public void display() {
		System.out.println("~~北京鸭~~~");
	}
	
	

}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

//玩具鸭
public class ToyDuck extends Duck{

	
	public ToyDuck() {
		flyBehavior = new NoFlyBehavior();
	}
	
	@Override
	public void display() {
		System.out.println("玩具鸭");
	}

	//需要重写父类的所有方法
	
	public void quack() {
		System.out.println("玩具鸭不能叫~~");
	}
	
	public void swim() {
		System.out.println("玩具鸭不会游泳~~");
	}
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

//野鸭
public class WildDuck extends Duck {

	
	//构造器,传入FlyBehavor 的对象
	public  WildDuck() {
		flyBehavior = new GoodFlyBehavior();
	}
	
	
	@Override
	public void display() {
		System.out.println(" 这是野鸭 ");
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design21;

public class Client {

	public static void main(String[] args) {
		WildDuck wildDuck = new WildDuck();
		wildDuck.fly();//
		
		ToyDuck toyDuck = new ToyDuck();
		toyDuck.fly();
		
		PekingDuck pekingDuck = new PekingDuck();
		pekingDuck.fly();
		
		//动态改变某个对象的行为, 北京鸭 不能飞
		pekingDuck.setFlyBehavior(new NoFlyBehavior());
		System.out.println("北京鸭的实际飞翔能力");
		pekingDuck.fly();
	}

}

策略模式在JDK-Arrays应用源码分析:

解释:

Comparator 相当于一个策略接口,第一种方式它的实现为内部类,第二种实现相当于用lambda表达式

package com.hjm.shd.shardingspheredemo.designPatterns.jdk;

import java.util.Arrays;
import java.util.Comparator;


public class Strategy {

	public static void main(String[] args) {
		//数组
		Integer[] data = { 9, 1, 2, 8, 4, 3 };
		Integer[] data33 = new Integer[5];
		data33[0] =1;
		data33[2] = 2;
		System.out.println(Arrays.toString(data33));
		// 实现降序排序,返回-1放左边,1放右边,0保持不变
		
		// 说明
		// 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator<Integer>(){..}
		// 2. 对象 new Comparator<Integer>(){..} 就是实现了 策略接口 的对象
		// 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式
		Comparator<Integer> comparator = new Comparator<Integer>() {
			public int compare(Integer o1, Integer o2) {
				if (o1 > o2) {
					return -1;
				} else {
					return 1;
				}
			};
		};

		// 说明
		/*
		 * public static <T> void sort(T[] a, Comparator<? super T> c) {
		        if (c == null) {
		            sort(a); //默认方法
		        } else { 
		            if (LegacyMergeSort.userRequested)
		                legacyMergeSort(a, c); //使用策略对象c
		            else
		            	// 使用策略对象c
		                TimSort.sort(a, 0, a.length, c, null, 0, 0);
		        }
		    }
		 */
		//方式1 
		Arrays.sort(data, comparator);
		
		System.out.println(Arrays.toString(data)); // 降序排序

		
		//方式2- 同时lambda 表达式实现 策略模式
		Integer[] data2 = { 19, 11, 12, 18, 14, 13 };
		
		Arrays.sort(data2, (var1, var2) -> {
			if(var1.compareTo(var2) > 0) {
				return -1;
			} else {
				return 1;
			}
		});
		System.out.println("data2=" + Arrays.toString(data2));
		
	}

}

策略模式优缺点:

1.策略模式的关键是,分析项目中变化部分与不变部分

2.策略模式核心是:多用组合/聚合,少用继承,用行为类组合,而不是行为的继承.更有弹性.

3.策略模式更好的体现了开闭原则,易于切换,易于理解,易于扩展

4.需要注意的是:每添加一个策略,就需要增加一个类,当策略过多实惠导致类数据庞大

职责链模式

职责链模式,又叫责任链模式,为请求创建了一个接收者对象的链,这种模式对于请求的发送者和接收者进行解耦

职责链模式通常每个接收者都包含另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依次类推.

使用场景:

学校OA采购审批项目:

原理类图:

1.Handler:抽象处理者,定义了一个处理请求的接口,同时含有另外Handler

2.ConcreteHandlerA,B 是具体的处理者,处理它自己负责的请求,可以访问它的后继者(即下一个处理者),如果可以处理当前请求,则处理,否则就将该请求交给后继者处理,从而形成一个责任链.

3.Request:含有很多属性,表示一个请求.

OA审批类图:

代码:

package com.hjm.shd.shardingspheredemo.designPatterns.design22;

//处理人抽象类
public abstract class Approver {

	Approver approver;  //下一个处理者
	String name; // 名字
	
	public Approver(String name) {
		this.name = name;
	}

	//下一个处理者
	public void setApprover(Approver approver) {
		this.approver = approver;
	}
	
	//处理审批请求的方法,得到一个请求, 处理是子类完成,因此该方法做成抽象
	public abstract void processRequest(PurchaseRequest purchaseRequest);
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design22;

//具体处理者 系主任处理
public class DepartmentApprover extends Approver {

	
	public DepartmentApprover(String name) {
		super(name);
	}
	
	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if(purchaseRequest.getPrice() <= 5000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		}else {
			approver.processRequest(purchaseRequest);
		}
	}

}
package com.hjm.shd.shardingspheredemo.designPatterns.design22;

//具体处理者 院系主任
public class CollegeApprover extends Approver {

	public CollegeApprover(String name) {
		super(name);
	}
	
	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if(purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		}else {
			approver.processRequest(purchaseRequest);
		}
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design22;

//具体处理者  副校长
public class ViceSchoolMasterApprover extends Approver {

	public ViceSchoolMasterApprover(String name) {
		super(name);
	}
	
	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if(purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		}else {
			approver.processRequest(purchaseRequest);
		}
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design22;

//具体处理者校长
public class SchoolMasterApprover extends Approver {

	public SchoolMasterApprover(String name) {
		super(name);
	}
	
	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if(purchaseRequest.getPrice() > 30000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		}else {
			approver.processRequest(purchaseRequest);
		}
	}
}
package com.hjm.shd.shardingspheredemo.designPatterns.design22;


//请求类
public class PurchaseRequest {

	private int type = 0; //请求类型
	private float price = 0.0f; //请求金额
	private int id = 0;
	//构造器
	public PurchaseRequest(int type, float price, int id) {
		this.type = type;
		this.price = price;
		this.id = id;
	}
	public int getType() {
		return type;
	}
	public float getPrice() {
		return price;
	}
	public int getId() {
		return id;
	}
	
	
	
	
	
}
package com.hjm.shd.shardingspheredemo.designPatterns.design22;

public class Client {

	public static void main(String[] args) {
		//创建一个请求
		PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 1);
		
		//创建相关的审批人
		DepartmentApprover departmentApprover = new DepartmentApprover("张主任");
		CollegeApprover collegeApprover = new CollegeApprover("李院长");
		ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校");
		SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("佟校长");
	
	
		//需要将各个审批级别的下一个设置好 (处理人构成环形: )
		departmentApprover.setApprover(collegeApprover);
		collegeApprover.setApprover(viceSchoolMasterApprover);
		viceSchoolMasterApprover.setApprover(schoolMasterApprover);
		schoolMasterApprover.setApprover(departmentApprover);
		
		
		
		departmentApprover.processRequest(purchaseRequest);
		viceSchoolMasterApprover.processRequest(purchaseRequest);
	}

}

职责链模式在SpringMVC框架源码分析:

SpringMVC流程图:

源码解析:

public static void main(String[] args) {
        // DispatcherServlet 

        //说明
		/*
		 * 
		 *  protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		 *   HandlerExecutionChain mappedHandler = null; 
		 *   mappedHandler = getHandler(processedRequest);//获取到HandlerExecutionChain对象
		 *    //在 mappedHandler.applyPreHandle 内部 得到啦 HandlerInterceptor interceptor
		 *    //调用了拦截器的  interceptor.preHandle
		 *   if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
				
			  //说明:mappedHandler.applyPostHandle 方法内部获取到拦截器,并调用 
			  //拦截器的  interceptor.postHandle(request, response, this.handler, mv);
			 mappedHandler.applyPostHandle(processedRequest, response, mv);
		 *  }
		 *  
		 *  
		 *  //说明:在  mappedHandler.applyPreHandle内部中,
		 *  还调用了  triggerAfterCompletion 方法,该方法中调用了  
		 *  HandlerInterceptor interceptor = getInterceptors()[i];
			try {
				interceptor.afterCompletion(request, response, this.handler, ex);
			}
			catch (Throwable ex2) {
				logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
			}
		 */

    }

说明:

springmvc请求流程图中,执行了拦截器相关方法 interceptor.preHandler 等等 在处理SpringMVC请求时,使用到了职责链模式和适配器模式

HandlerExecutionChain 主要负责的是请求拦截器的执行和请求处理,但是他本身不处理请求,只是将请求分配给链上的注册处理器执行,这是职责链实现方式,减少职责链本身与处理逻辑之间的耦合,规范了处理流程.

HandlerExecutionChain 维护了HandlerInterceptor 的集合,可以向其中注册响应的拦截器.

职责链模式的优缺点:

1.将请求和处理分开,实现了解耦,提高了系统的灵活性.

2.简化了对象,使对象不需要知道链的结构

3.性能会收到影响,特别是链比较长的时候,因此需要控制链中最大节点数量,一般通过Handler中设置一个最大节点数量,在setNext()方法中怕段是否已经超过阈值,超过则不允许该链建立,避免出现超长链无意识的破坏系统性能.

4.调试不方便,采用了类似递归的方式,调试逻辑比较复杂

5.最佳应用场景:有多个对象可以处理同一请求,比如:多级请求,请假/加薪等审批流程,java Web中Tomcat对Encoding的处理,拦截器.

小结:

至此,23中设计模式之行为型模型全部介绍完成,创建型模型和结构型模型,可以参考之前发的帖子.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值