Java设计模式(五):行为型模式(模板方法模式、命令模式、访问这模式、迭代器模式、观察者模式、中介模式)

目录

一· 模板方法模式

1.1 豆浆制作问题

编写制作豆浆的程序,说明如下: 
	1) 制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎 
	2) 通过添加不同的配料,可以制作出不同口味的豆浆 
	3) 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的 
	4) 请使用 模板方法模式 完成 	(说明:因为模板方法模式,比较简单,很容易就想到这个方案,因此就直接使用, 不再使用传统的方案来引出模板方法模式 	)

1.2 模板方法模式基本介绍

基本介绍 
	1) 模板方法模式(Template Method Pattern),又叫模板模式(Template 	Pattern),z 在一个抽象类公开定义了执行 它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 
	2) 简单说,模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一 个算法的结构,就可以重定义该算法的某些特定步骤 
	3) 这种类型的设计模式属于行为型模式。 

1.3 模板方法模式原理类图

  1. 模板方法模式的原理类图
    在这里插入图片描述

       对原理类图的说明-即(模板方法模式的角色及职责) 
    
1) AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象 方法 operationr2,3,4 
2) ConcreteClass 实现抽象方法 operationr2,3,4, 以完成算法中特点子类的步骤 

1.4 模板方法模式解决豆浆制作问题

1) 应用实例要求 
	编写制作豆浆的程序,说明如下: 
	制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎 
	通过添加不同的配料,可以制作出不同口味的豆浆 
	选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的(红豆、花生豆浆。。。) 
2) 思路分析和图解(类图)

在这里插入图片描述

3)代码实现
package com.atzhu.template; 



public class Client { 


	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//制作红豆豆浆 
		System.out.println("----制作红豆豆浆----"); 
		SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk(); 
		redBeanSoyaMilk.make(); 


		System.out.println("----制作花生豆浆----"); 
		SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk(); 
		peanutSoyaMilk.make(); 
	}
}



package com.atzhu.template; 


public class PeanutSoyaMilk extends SoyaMilk { 


	@Override 
	void addCondiments() { 
		// TODO Auto-generated method stub 
		System.out.println(" 加入上好的花生 "); 
	}
}



package com.atzhu.template; 


public class RedBeanSoyaMilk extends SoyaMilk { 


	@Override 
	void addCondiments() { 
		// TODO Auto-generated method stub 
		System.out.println(" 加入上好的红豆 "); 
	}
}



package com.atzhu.template; 


//抽象类,表示豆浆 
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("第四步:黄豆和配料放到豆浆机去打碎 "); 
	}
}

1.5 模板方法模式的钩子方法

1) 在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方 法称为"钩子"。 
2) 还是用上面做豆浆的例子来讲解,比如,我们还希望制作纯豆浆,不添加任何的配料,请使用钩子方法对前面 的模板方法进行改造 
3) 看代码演示:
package com.atzhu.template.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; 
	}
}

1.6 模板方法模式在 Spring 框架应用的源码分析

1) Spring IOC 容器初始化时运用到的模板方法模式 
2) 代码分析+角色分析+说明类图

在这里插入图片描述

3) 针对源码的类图(说明层次关系)

在这里插入图片描述

1.7 模板方法模式的注意事项和细节

1) 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方 法或者已经实现的某些步骤,子类就会继承这些修改 
2) 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。 
3) 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步 骤的实现。 
4) 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大 
5) 一般模板方法都加上 final 关键字, 防止子类重写模板方法. 
6) 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤 ,
	这一系列的步骤基本相同,但其 个别步骤在实现时 可能不同,通常考虑用模板方法模式来处理 

二· 命令模式

2.1 智能生活项目需求

看一个具体的需求

在这里插入图片描述

1) 我们买了一套智能家电,有照明灯、风扇、冰箱、洗衣机,我们只要在手机上安装 app 就可以控制对这些家电 工作。 

2) 这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个 App,分别控制,我们希望只要一个 app 就可以控制全部智能家电。 

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

4) 命令模式可将"动作的请求者"从"动作的执行者"对象中解耦出来. 
5) 在我们的例子中,动作的请求者是手机 app,动作的执行者是每个厂商的一个家电产品 

2.2 命令模式基本介绍

1) 命令模式(Command Pattern):在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收 者是谁,也不知道被请求的操作是哪个, 
	我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计 
2) 命名模式使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活,实现解耦。 
3) 在命名模式中,会将一个请求封装为一个对象,以便使用不同参数来表示不同的请求(即命名),同时命令模式 也支持可撤销的操作。 
4) 通俗易懂的理解:将军发布命令,士兵去执行。其中有几个角色:将军(命令发布者)、士兵(命令的具体执 行者)、命令(连接将军和士兵)。 
	Invoker 是调用者(将军),Receiver 是被调用者(士兵),MyCommand 是命令,实现了 Command 接口,持 有接收对象 

2.3 命令模式的原理类图

在这里插入图片描述

对原理类图的说明-即(命名模式的角色及职责) 
	1) Invoker 是调用者角色 
	2) Command: 是命令角色,需要执行的所有命令都在这里,可以是接口或抽象类 
	3) Receiver: 接受者角色,知道如何实施和执行一个请求相关的操作 
	4) ConcreteCommand: 将一个接受者对象与一个动作绑定,调用接受者相应的操作,实现 execute 

2.4 命令模式解决智能生活项目

应用实例要求 
	1) 编写程序,使用命令模式 完成前面的智能家电项目 
	2) 思路分析和图解

在这里插入图片描述

3)代码实现
package com.atzhu.command; 



public class Client { 


	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//使用命令设计模式,完成通过遥控器,对电灯的操作 
		//创建电灯的对象(接受者) 
		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.atzhu.command; 
 


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

	//执行动作(操作) 
	public void execute(); 
	//撤销动作(操作) public void undo(); 
}



package com.atzhu.command; 



public class LightOffCommand implements Command { 

	// 聚合 LightReceiver 
	LightReceiver light; 

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



	@Override 
	public void execute() { 
		// TODO Auto-generated method stub 
		// 调用接收者的方法 
		light.off(); 
	}



	@Override 
	public void undo() { 
		// TODO Auto-generated method stub 
		// 调用接收者的方法 
		light.on(); 
	}
}

package com.atzhu.command; 



public class LightOnCommand implements Command { 


	//聚合 LightReceiver 
	LightReceiver light; 


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


	@Override 
	public void execute() { 
		// TODO Auto-generated method stub 
		//调用接收者的方法 
		light.on(); 
	}
 

	@Override 
	public void undo() { 
		// TODO Auto-generated method stub 
		//调用接收者的方法 
		light.off(); 
	}
}
 



package com.atzhu.command; 



public class LightReceiver { 



	public void on() { 
		System.out.println(" 电灯打开了.. "); 
	}



	public void off() { 
		System.out.println(" 电灯关闭了.. "); 
	}
}



package com.atzhu.command; 



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


	@Override 
	public void execute() { 
		// TODO Auto-generated method stub 
	}



	@Override 
	public void undo() { 
		// TODO Auto-generated method stub 
	}
}



package com.atzhu.command; 



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.atzhu.command; 


public class TVOffCommand implements Command { 


	// 聚合 TVReceiver 
	TVReceiver tv; 


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


	@Override 
	public void execute() { 
		// TODO Auto-generated method stub 
		// 调用接收者的方法 
		tv.off(); 
	}


	@Override 
	public void undo() { 
		// TODO Auto-generated method stub 
		// 调用接收者的方法 
		tv.on(); 
	}
}



package com.atzhu.command; 



public class TVOnCommand implements Command { 


	// 聚合 TVReceiver 
	TVReceiver tv; 


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


	@Override 
	public void execute() { 
		// TODO Auto-generated method stub 
		// 调用接收者的方法 
		tv.on(); 
	}


	@Override 
	public void undo() { 
		// TODO Auto-generated method stub 
		// 调用接收者的方法 
		tv.off(); 
	}
}


package com.atzhu.command; 


public class TVReceiver { 


	public void on() { 
		System.out.println(" 电视机打开了.. "); 
	}


	public void off() { 
		System.out.println(" 电视机关闭了.. "); 
	}
}

2.5 命令模式在 Spring 框架 JdbcTemplate 应用的源码分析

1) Spring 框架的 JdbcTemplate 就使用到了命令模式 
2) 代码分析

在这里插入图片描述

3) 模式角色分析说明 

	StatementCallback 接口 ,类似命令接口(Command) 
	class QueryStatementCallback implements StatementCallback<T>, SqlProvider , 匿名内部类, 实现了命令接口, 同时也充当命令接收者 

	命令调用者 是 JdbcTemplate , 其中 execute(StatementCallback<T> action) 方法中, 用 action.doInStatement 方 调法. 	不同的 实现 StatementCallback 接口的对象,对应不同的 doInStatemnt 实现逻辑 
	另外实现 StatementCallback 命令接口的子类还有 QueryStatementCallback

在这里插入图片描述

2.6 命令模式的注意事项和细节

1) 将发起请求的对象与执行请求的对象解耦。
	发起请求的对象是调用者,调用者只要调用命令对象的 execute()方 法就可以让接收者工作,而不必知道具体的接收者对象是谁、是如何实现的,命令对象会负责让接收者执行请 求的动作,
	也就是说:"请求发起者"和"请求执行者"之间的解耦是通过命令对象实现的,命令对象起到了 纽带桥梁的作用。 
2) 容易设计一个命令队列。只要把命令对象放到列队,就可以多线程的执行命令 
3) 容易实现对请求的撤销和重做 
4) 命令模式不足:可能导致某些系统有过多的具体命令类,增加了系统的复杂度,这点在在使用的时候要注意 
5) 空命令也是一种设计模式,它为我们省去了判空的操作。在上面的实例中,如果没有用空命令,我们每按下一 个按键都要判空,这给我们编码带来一定的麻烦。 
6) 命令模式经典的应用场景:界面的一个按钮都是一条命令、模拟 CMD(DOS 命令)订单的撤销/恢复、触发- 反馈机制 

三· 访问者模式

3.1 测评系统的需求

完成测评系统需求 

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

在这里插入图片描述

3.2 传统方式的问题分析

1) 如果系统比较小,还是 ok 的,但是考虑系统增加越来越多新的功能时,对代码改动较大,违反了 ocp 原则, 不 利于维护 
2) 扩展性不好,比如 增加了 新的人员类型,或者管理方法,都不好做 
3) 引出我们会使用新的设计模式 - 访问者模式 

3.3 访问者模式基本介绍

1) 访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前 提下定义作用于这些元素的新的操作。 
2) 主要将数据结构与数据操作分离,解决 数据结构和操作耦合性问题 
3) 访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口 
4) 访问者模式主要应用场景是:需要对一个对象结构中的对象进行很多不同操作(这些操作彼此没有关联),同时 需要避免让这些操作"污染"这些对象的类,可以选用访问者模式解决 

3.4 访问者模式的原理类图

在这里插入图片描述

	对原理类图的说明- 
		即(访问者模式的角色及职责)
1) Visitor 是抽象访问者,为该对象结构中的 ConcreteElement 的每一个类声明一个 visit 操作 
2) ConcreteVisitor :是一个具体的访问值 实现每个有 Visitor 声明的操作,是每个操作实现的部分. 
3) ObjectStructure 能枚举它的元素, 可以提供一个高层的接口,用来允许访问者访问元素 
4) Element 定义一个 accept 方法,接收一个访问者对象 
5) ConcreteElement 为具体元素,实现了 accept 方法

3.5 访问者模式应用实例

应用实例要求 
	1) 将人分为男人和女人,对歌手进行测评,当看完某个歌手表演后,得到他们对该歌手不同的评价(评价 有不同 的种类,比如 成功、失败 等),请使用访问者模式来说实现 
	2) 思路分析和图解(类图)

在这里插入图片描述

3)代码实习
package com.atzhu.visitor; 



public abstract class Action { 

	//得到男性 的测评 
	public abstract void getManResult(Man man); 

	//得到女的 测评 
	public abstract void getWomanResult(Woman woman); 
}



package com.atzhu.visitor; 



public class Client { 


	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//创建 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); 
	}
}



package com.atzhu.visitor; 



public class Fail extends Action { 



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



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





package com.atzhu.visitor; 



public class Man extends Person { 


	@Override 
	public void accept(Action action) { 
		// TODO Auto-generated method stub 
		action.getManResult(this); 
	}
}



package com.atzhu.visitor; 



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



package com.atzhu.visitor; 


public abstract class Person { 


	//提供一个方法,让访问者可以访问 
	public abstract void accept(Action action); 
	}



package com.atzhu.visitor; 



public class Success extends Action { 


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


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



package com.atzhu.visitor; 



public class Wait extends Action { 


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


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



package com.atzhu.visitor; 



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



	@Override 
	public void accept(Action action) { 
		// TODO Auto-generated method stub 
		action.getWomanResult(this); 
	}
}
4) 应用案例的小结-双分派 


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

	- 以上述实例为例,假设我们要添加一个 Wait 的状态类,考察 Man 类和 Woman 类的反应,
	- 由于使用了双分 派,只需增加一个 Action 子类即可在客户端调用即可,不需要改动任何其他类的代码。 

3.6 访问者模式的注意事项和细节

	优点 

1) 访问者模式符合单一职责原则、让程序具有优秀的扩展性、灵活性非常高 
2) 访问者模式可以对功能进行统一,可以做报表、UI、拦截器与过滤器,适用于数据结构相对稳定的系统 
	缺点 

1) 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的, 这样造 成了具体元素变更比较困难 
2) 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素 
3) 因此,如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的.

四· 迭代器模式

4.1 看一个具体的需求

编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 
一个学院有多个系。如图:

在这里插入图片描述

4.2 传统的设计方案(类图)

在这里插入图片描述

4.3 传统的方式的问题分析

1) 将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的 
2) 实际上我们的要求是 :在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系, 因 此这种方案,不能很好实现的遍历的操作 
3) 解决方案:=> 迭代器模式 

4.4 迭代器模式基本介绍

基本介绍 

1) 迭代器模式(Iterator Pattern)是常用的设计模式,属于行为型模式 
2) 如果我们的集合元素是用不同的方式实现的,有数组,还有 java 的集合类,或者还有其他方式,当客户端要遍 历这些集合元素的时候就要使用多种遍历方式, 且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。 而
3) 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表 示,即:不暴露其内部的结构。 

4.5 迭代器模式的原理类图

在这里插入图片描述

对原理类图的说明-即(迭代器模式的角色及职责) 
	1) Iterator : 迭代器接口,是系统提供,含义 hasNext, next, remove 
	2) ConcreteIterator : 具体的迭代器类,管理迭代 
	3) Aggregate :一个统一的聚合接口, 将客户端和具体聚合解耦 
	4) ConcreteAggreage : 具体的聚合持有对象集合, 并提供一个方法,返回一个迭代器, 该迭代器可以正确遍历 集合 
	5) Client :客户端, 通过 Iterator 和 Aggregate 依赖子类 

4.6 迭代器模式应用实例

1) 应用实例要求 
	编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。 
2) 设计思路分析

在这里插入图片描述

3)代码实现
package com.atzhu.iterator; 



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



public class Client { 



	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//创建学院 
		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(); 
	}
}



package com.atzhu.iterator; 



import java.util.Iterator; 



public interface College { 
 

	public String getName(); 



	//增加系的方法 
	public void addDepartment(String name, String desc); 



	//返回一个迭代器,遍历 
	public Iterator 	createIterator(); 
}



package com.atzhu.iterator; 



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() { 
		// TODO Auto-generated method stub 
		return "计算机学院"; 
	}



	@Override 
	public void addDepartment(String name, String desc) { 
		// TODO Auto-generated method stub 
		Department department = new Department(name, desc); 
		departments[numOfDepartment] = department; 
		numOfDepartment += 1; 
	}



	@Override 
	public Iterator createIterator() { 
		// TODO Auto-generated method stub 
		return new ComputerCollegeIterator(departments); 
	}
}



package com.atzhu.iterator; 


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() { 
		// TODO Auto-generated method stub 
		if(position >= departments.length || departments[position] == null) { 
			return false; 
		}else { 
			return true; 
		}
	}



	@Override 
	public Object next() { 
		// TODO Auto-generated method stub 
		Department department = departments[position]; 
		position += 1; 
		return department; 
	}



	//删除的方法,默认空实现 
	public void remove() { 
	}
}



package com.atzhu.iterator; 



//系 
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.atzthu.iterator; 



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() { 
		// TODO Auto-generated method stub 
		if(index >= departmentList.size() - 1) { 
			return false; 
		} else { 
			index += 1; return true; 
		}
	}



	@Override 
	public Object next() { 
		// TODO Auto-generated method stub 
		return departmentList.get(index); 
	}



	//空实现 remove 
	public void remove() { 
	}
}



package com.atzhu.iterator; 



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() { 
		// TODO Auto-generated method stub 
		return "信息工程学院"; 
	}



	@Override 
	public void addDepartment(String name, String desc) { 
		// TODO Auto-generated method stub 
		Department department = new Department(name, desc); 
		departmentList.add(department); 
	}



	@Override 
	public Iterator createIterator() { 
		// TODO Auto-generated method stub 
		return new InfoColleageIterator(departmentList); 
	}
}



package com.atzhu.iterator; 



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

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

1) JDK 的 ArrayList 集合中就使用了迭代器模式 
2) 代码分析+类图+说明 

在这里插入图片描述
在这里插入图片描述

3) 对类图的角色分析和说明 
	内部类 Itr 充当具体实现迭代器 Iterator 的类, 作为 ArrayList 内部类 
	List 就是充当了聚合接口,含有一个 iterator() 方法,返回一个迭代器对象 
	ArrayList 是实现聚合接口 List 的子类,实现了 iterator() 
	Iterator 接口系统提供 
	迭代器模式解决了 不同集合(ArrayList ,LinkedList) 统一遍历问题 

4.8 迭代器模式的注意事项和细节

优点 
	1) 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。 
	2) 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。 
	3) 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。
		在聚合类中,我们把 迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。 
		而如果遍历方式改变的话,只影响到了迭代器。 
	4) 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式 

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

五· 观察者模式

5.1 天气预报项目需求,具体要求如下:

1) 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。 
2) 需要设计开放型 API,便于其他第三方也能接入气象站获取数据。 
3) 提供温度、气压和湿度的接口 
4) 测量数据更新时,要能实时的通知给第三方 

5.2 天气预报设计方案 1-普通方案

  1. WeatherData 类

       传统的设计方案
    

在这里插入图片描述

package com.atzhu.observer; 



public class Client { 
	public static void main(String[] args) { 
		//创建接入方 currentConditions 
		CurrentConditions currentConditions = new CurrentConditions(); 
		//创建 WeatherData 并将 接入方 currentConditions 传递到 WeatherData 中 
		WeatherData weatherData = new WeatherData(currentConditions); 



		//更新天气情况 
		weatherData.setData(30, 150, 40); 



		//天气情况变化 
		System.out.println("============天气情况变化============="); 
		weatherData.setData(40, 160, 20); 
	}
}



package com.atzhu.observer; 



/ ** 
* 显示当前天气情况(可以理解成是气象站自己的网站) 
* @author Administrator 
*
*/ 
public class CurrentConditions { 
	// 温度,气压,湿度 
	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.atzhu.observer; 



/ ** 
* 类是核心 
* 1. 包含最新的天气情况信息 
* 2. 含有 CurrentConditions 对象 
* 3. 当数据有更新时,就主动的调用 
到最新的信息 

* @author Administrator 
*
*/ 
public class WeatherData { 
	private float temperatrue; 
	private float pressure; 
	private float humidity; 
 

	CurrentConditions 对象 update 方法(含 display), 这样他们(接入方)就看 
 
	private CurrentConditions currentConditions; 
	//加入新的第三方 
	public WeatherData(CurrentConditions currentConditions) { 
		this.currentConditions = currentConditions; 
	}



	public float getTemperature() { 
		return temperatrue; 
	}



	public float getPressure() { 
		return pressure; 
	}



	public float getHumidity() { 
		return humidity; 
	}



	public void dataChange() { 
		//调用 接入方的 update 
		currentConditions.update(getTemperature(), getPressure(), getHumidity()); 
	}



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

1) 其他第三方接入气象站获取数据的问题 
2) 无法在运行时动态的添加第三方 (新浪网站) 
3) 违反 ocp 原则=>观察者模式 
public void dataChange() { 
	//在 WeatherData 中, 增加一个第三方, 需要创建一个对应的第三方的公告板对象, 加入到 dataChange, 不 
	currentConditions.update(getTemperature(), getPressure(), getHumidity()); 
}

5.3 观察者模式原理

1) 观察者模式类似订牛奶业务 
2) 奶站/气象局:Subject 
3) 用户/第三方网站:Observer 



	Subject:登记注册、移除和通知 
1) registerObserver 注册 
2) removeObserver 移除 
3) notifyObservers() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送, 看具体需求定 

	Observer:接收输入 
	观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为 Subject,依赖的对象为 Observer,Subject 通知 Observer 变化,比如这里的奶站是 Subject,是 1 的一方。用户时 Observer,是多的一方。 

5.4 观察者模式解决天气预报需求

  1. 类图说明
    在这里插入图片描述

  2. 代码实现
    
package com.atzhu.observer.improve; 



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.atzhu.observer.improve; 



public class Client { 



	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//创建一个 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(); 
		System.out.println("通知各个注册的观察者, 看看信息"); 
		weatherData.setData(10f, 100f, 30.3f); 
	}
}
 



package com.atzhu.observer.improve; 



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.atzhu.observer.improve; 



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



	public void update(float temperature, float pressure, float humidity); 
	}


package com.atzhu.observer.improve; 



//接口, 让 WeatherData 来实现 
public interface Subject { 


	public void registerObserver(Observer o); 
	public void removeObserver(Observer o); 
	public void notifyObservers(); 
	}



package com.atzhu.observer.improve; 



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) { 
		// TODO Auto-generated method stub 
		observers.add(o); 
	}



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



	//遍历所有的观察者,并通知 
	@Override 
	public void notifyObservers() { 
		// TODO Auto-generated method stub 
		for(int i = 0; i < observers.size(); i++) { 
			observers.get(i).update(this.temperatrue, this.pressure, this.humidity); 
		}
	}
}
  1. 观察者模式的好处
1) 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。 
2) 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类 WeatherData 不会修改代码, 遵守了 ocp 原则。 

5.5 观察者模式在 Jdk 应用的源码分析

1) Jdk 的 Observable 类就使用了观察者模式 
2) 代码分析+模式角色分析

在这里插入图片描述

3) 模式角色分析 
	Observable 的作用和地位等价于 我们前面讲过 Subject 
	Observable 是类,不是接口,类中已经实现了核心的方法 ,即管理 Observer 的方法 add.. delete .. notify... 
	Observer 的作用和地位等价于我们前面讲过的 Observer, 有 update 
	Observable 和 Observer 的使用方法和前面讲过的一样,只是 Observable 是类,通过继承来实现观察者模式 

六· 中介者模式

6.1 智能家庭项目

在这里插入图片描述

	智能家庭项目: 

1) 智能家庭包括各种设备,闹钟、咖啡机、电视机、窗帘 等 
2) 主人要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,比如流程为:闹铃响起->咖啡机开始 做咖啡->窗帘自动落下->电视机开始播放 

6.2 传统方案解决智能家庭管理问题

在这里插入图片描述

6.3 传统的方式的问题分析

1) 当各电器对象有多种状态改变时,相互之间的调用关系会比较复杂 
2) 各个电器对象彼此联系,你中有我,我中有你,不利于松耦合. 
3) 各个电器对象之间所传递的消息(参数),容易混乱 
4) 当系统增加一个新的电器对象时,或者执行流程改变时,代码的可维护性、扩展性都不理想 

6.4 中介者模式基本介绍

基本介绍 
	1) 中介者模式(Mediator Pattern),用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地 相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互 
	2) 中介者模式属于行为型模式,使代码易于维护 
	3) 比如 MVC 模式,C(Controller 控制器)是 M(Model 模型)和 V(View 视图)的中介者,在前后端交互时起 到了中间人的作用 

6.5 中介者模式的原理类图

在这里插入图片描述

对原理类图的说明-即(中介者模式的角色及职责) 
	1) Mediator 就是抽象中介者,定义了同事对象到中介者对象的接口 
	2) Colleague 是抽象同事类 
	3) ConcreteMediator 具体的中介者对象, 实现抽象方法, 他需要知道所有的具体的同事类,即以一个集合来管理 HashMap,并接受某个同事对象消息,完成相应的任务 
	4) ConcreteColleague 具体的同事类, 有很多, 每个同事只知道自己的行为, 而不了解其他同事类的行为(方法), 会但是他们都依赖中介者对象 

6.6 中介者模式应用实例-智能家庭管理

1) 应用实例要求 
	完成前面的智能家庭的项目,使用中介者模式 
2) 思路分析和图解(类图)

在这里插入图片描述

3)代码实现
package com.atzhu.mediator.smarthouse; 



//具体的同事类 
public class Alarm extends Colleague { 



	//构造器 
	public Alarm(Mediator mediator, String name) { 


		super(mediator, name); 
		// TODO Auto-generated constructor stub 
		//在创建 Alarm 同事对象时,将自己放入到 ConcreteMediator 对象中[集合] 
		mediator.Register(name, this); 
	}



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



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

}



package com.atzhu.mediator.smarthouse; 



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

}
 



package com.atzhu.mediator.smarthouse; 



public class CoffeeMachine extends Colleague { 



	public CoffeeMachine(Mediator mediator, String name) { 
		super(mediator, name); 

		// TODO Auto-generated constructor stub 
		mediator.Register(name, this); 
	}



	@Override 
	public void SendMessage(int stateChange) { 
		// TODO Auto-generated method stub 
		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.atzhu.mediator.smarthouse; 



//同事抽象类 
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.atzhu.mediator.smarthouse; 



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) { 
		// TODO Auto-generated method stub 
		colleagueMap.put(colleagueName, colleague); 



		// TODO Auto-generated method stub 
		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) { 
		// TODO Auto-generated method stub 
		//处理闹钟发出的消息 
		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() { 
		// TODO Auto-generated method stub 
	}
 
}



package com.atzhu.mediator.smarthouse; 



public class Curtains extends Colleague { 



	public Curtains(Mediator mediator, String name) { 
		super(mediator, name); 
		// TODO Auto-generated constructor stub 
		mediator.Register(name, this); 
	}



	@Override 
	public void SendMessage(int stateChange) { 
		// TODO Auto-generated method stub 
		this.GetMediator().GetMessage(stateChange, this.name); 
	}

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



package com.atzhu.mediator.smarthouse; 



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.atzhu.mediator.smarthouse; 



public class TV extends Colleague { 



	public TV(Mediator mediator, String name) { 
		super(mediator, name); 
		// TODO Auto-generated constructor stub 
		mediator.Register(name, this); 
	}



	@Override 
	public void SendMessage(int stateChange) { 
		// TODO Auto-generated method stub 
		this.GetMediator().GetMessage(stateChange, this.name); 
	}



	public void StartTv() { 
		// TODO Auto-generated method stub 
		System.out.println("It's time to StartTv!"); 
	}



	public void StopTv() { 
		// TODO Auto-generated method stub 
		System.out.println("StopTv!"); 
	}
}

6.7 中介者模式的注意事项和细节

1) 多个类相互耦合,会形成网状结构, 使用中介者模式将网状结构分离为星型结构,进行解耦 
2) 减少类间依赖,降低了耦合,符合迪米特原则 
3) 中介者承担了较多的责任,一旦中介者出现了问题,整个系统就会受到影响 
4) 如果设计不当,中介者对象本身变得过于复杂,这点在实际使用时,要特别注意
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱yoyo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值