观察者模式:发布者持有订阅者列表,当发布者变化时通知观察者列表。
模板模式:抽象父类规范主方法,调用内部的抽象方法由具体子类重写实现。
命令模式:命令者下发命令到一个系统接收命令类,由这个类去找合适的执行者,比如一个智能遥控器包括电脑、门、灯的开关功能,我们只需使用遥控去下发这个命令。
状态模式:
责任链模式:先判断自己能否处理,如果不能就交给下一个链处理。
1、观察者模式
一个被观察的类在状态发生变化时,需要主动发出消息来通知订阅它的观察者类。
定义观察者
public interface Observer {
void update(Observable o);
}
public class ConcreteObserver1 implements Observer{
public void update(Observable o) {
System.out.println("观察者1观察到" + o.getClass().getSimpleName() + "发生变化");
System.out.println("update");
}
}
public class ConcreteObserver2 implements Observer{
public void update(Observable o) {
System.out.println("观察者2观察到" + o.getClass().getSimpleName() + "发生变化");
System.out.println("update");
}
}
//被观察者
public class Observable {
List<Observer> observers = new ArrayList<Observer>();
public void addObserver(Observer o){
observers.add(o);
}
public void changed(){
//通知观察自己的所有观察者
notifyObservers();
}
public void notifyObservers(){
for (Observer observer : observers) {
observer.update(this);
}
}
}
实际应用,比如我们订阅新闻时,当有更新时,订阅者会收到更新通知。
1、tomcat中的Listener,当加载spring配置文件时,tomcat启动那么 spring的IOC容器就会跟着启动。
2、spring中的ServletContextListener会监听 ServletContext的启动和销毁。
2、模板模式
为了统一子类的算法实现步骤,所使用的一种手段或者说是方式。它在父类中定义一系列算法的步骤,而将具体的实现都推迟到子类。
通常定义一个功能接口,再定一个抽象类实现这个接口,抽象类会再定义一些抽象方法并实现这个接口方法,接口方法里面会调用定义的抽象方法。这样不同子类重写抽象方法增加一定的灵活性,并且父类也规范了实现步骤。
优点
1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
public interface JobTask {
Result execute();
}
public abstract class defaultJob{
@Override
public Result execute() {
try {
checkParameter();
//调用抽象方法,子类会重写抽方法
return process();
} catch (Exception ex) {
}
return null;
}
protected abstract Result process();
}
//子类job
public class ModelJob extends defaultJob{
@Override
public Result process() {
//do some thing...
return Result;
}
}
比如类加载器就用的模板方法
public abstract class ClassLoader {
//这是一个重载方法
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
//这里就是父类算法的定义
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
//这里留了一个方法给子类选择性覆盖
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
}
从代码上我们可以看出,在ClassLoader中定义的算法顺序是。
* 1,首先看是否有已经加载好的类。
* 2,如果父类加载器不为空,则首先从父类类加载器加载。
* 3,如果父类加载器为空,则尝试从启动加载器加载。
* 4,如果两者都失败,才尝试从findClass方法加载。
这是JDK类加载器的双亲委派模型,即先从父类加载器加载,直到继承体系的顶层,否则才会采用当前的类加载器加载。这样做的目的是为了JVM中类的一致性。
3、命令模式
请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
比如你提交开灯、关灯、开门、关灯等多个命令给智能遥控,由智能遥控分配任务给执行者去执行相应任务,而不需你自己单个去发送命令。
//具体命令执行者
public class Light{
public void on(){
System.out.println("打开电灯");
}
public void off(){
System.out.println("关闭电灯");
}
}
//定义命令
public interface Command{
public void execute();
}
public class LightOffCommond implements Command{
private Light light ;
public LightOffCommond(Light light){
this.light = light;
}
@Override
public void execute(){
light.off();
}
}
public class LightOnCommond implements Command{
private Light light ;
public LightOnCommond(Light light){
this.light = light;
}
@Override
public void execute(){
light.on();
}
}
//接收命令类,再找到合适的执行者执行任务
public class ControlPanel{
private static final int CONTROL_SIZE = 9;
private Command[] commands;
public ControlPanel() {
commands = new Command[CONTROL_SIZE];
/**
* 初始化所有按钮指向空对象
*/
for (int i = 0; i < CONTROL_SIZE; i++)
{
commands[i] = new NoCommand();
}
}
/**
* 设置每个按钮对应的命令
* @param index
* @param command
*/
public void setCommand(int index, Command command){
commands[index] = command;
}
/**
* 模拟点击按钮
* @param index
*/
public void keyPressed(int index){
commands[index].execute();
}
}
//命令人
public static void main(String[] args) {
Light light = new Light();
ControlPanel controlPanel = new ControlPanel();
// 为每个按钮设置功能
controlPanel.setCommand(0, new LightOnCommond(light));
controlPanel.setCommand(1, new LightOffCommond(light));
// 模拟点击
controlPanel.keyPressed(0);
controlPanel.keyPressed(2);
controlPanel.keyPressed(3);
controlPanel.keyPressed(4);
controlPanel.keyPressed(5);
controlPanel.keyPressed(8);// 这个没有指定,但是不会出任何问题,我们的NoCommand的功劳
}
4、状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
5、责任链模式
责任链模式就是将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象进行处理,以此类推。
比如审批财物报销,如果小于500则由主管批,500-1000由经理批,1000-2000由部经理批,大于2000不予报销等。
//请求对象
public class Request {
private String name;
private int money;
public LeaveRequest(String name, int money) {
super();
this.name = name;
this.money = money;
}
//省略get和set方法
}
//责任链
public abstract class Leader {
protected String name;
//责任链上的后继对象,即这个对象无法处理,就转移给下一个Leader
protected Leader nextLeader;
public Leader(String name) {
super();
this.name = name;
}
// 设定责任链上的后继对象
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
/**
* 处理请求的核心的业务方法
* 需要不同继承该类的领导自己实现
*/
public abstract void handleRequest(LeaveRequest request);
}
//主任
public class Director extends Leader {
public Director(String name) {
super(name);
}
@Override
public void handleRequest(Request request) {
//获取请假天数
int money = request.getMoney();
String name = request.getName(); //获取请假人姓名
//如果小于500元,主任直接审批
if(days <= 500) {
System.out.println("员工" + name + "报销" + money + "元" );
System.out.println("主任" + this.name + "审批通过");
} else {
System.out.println("审批金额过多,主任" + this.name + "没法处理");
//否则,如果链上存在下一个Leader,就让他处理
if(this.nextLeader != null) {
this.nextLeader.handleRequest(request);
}
}
}
}
/**
* @Description 经理
*/
public class Manager extends Leader {
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(Request request) {
int money = request.getMoney();
String name = request.getName(); //获取请假人姓名
//如果小于1000的要求,经理直接审批
if(days <= 1000) {
System.out.println("员工" + name + "报销" + money + "元" );
System.out.println("经理" + this.name + "审批通过");
} else {
System.out.println("报销过多,经理" + this.name + "没法处理");
//否则,如果链上存在下一个Leader,就让他处理
if(this.nextLeader != null) {
this.nextLeader.handleRequest(request);
}
}
}
}
/**
* @Description 总经理
*/
public class GeneralManager extends Leader {
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(Request request) {
int money = request.getMoney();
String name = request.getName(); //获取请假人姓名
if(money <= 2000) {
System.out.println("员工" + name + "报销" + money + "天,理由:" + reason);
System.out.println("总经理" + this.name + "审批通过");
} else {
System.out.println("报销过多,总经理" + this.name + "没法处理");
if(this.nextLeader != null) { //否则,如果链上存在下一个Leader,就让他处理
this.nextLeader.handleRequest(request);
} else {
System.out.println("报销不成功");
}
}
}
}
//调用
public class Client {
public static void main(String[] args) {
Leader director = new Director("张三");
Leader manager = new Manager("李四");
Leader gManager = new GeneralManager("王五");
// 组织好责任链对象的关系
director.setNextLeader(manager);
manager.setNextLeader(gManager);
// 开始请假操作
LeaveRequest request = new Request("倪升武", 1000);
director.handleRequest(request);
}
}