职责链模式、迭代器模式、中介者模式、命令模式、解释器模式、访问者模式、策略模式、模版方法模式、状态模式、观察者模式、备忘录模式
一、职责链模式(Chain of responsibility)
1.1、作用:将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象
1.2、UML图:
1.3、示例:
public class 请假条 {
private String name;
private int days;
private String reason;
public 请假条(String name, int days, String reason) {
super();
this.name = name;
this.days = days;
this.reason = reason;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDays() {
return days;
}
public void setDays(int days) {
this.days = days;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}
--------------------------------------------------------------------------------
public abstract class 领导 {
protected String name;
protected 领导 nextLeader;
public 领导(String name) {
super();
this.name = name;
}
public void setNextLeader(领导 nextLeader) {
this.nextLeader = nextLeader;
}
public abstract void handelRequest(请假条 request);
}
--------------------------------------------------------------------------------
public class 主任 extends 领导{
public 主任(String name) {
super(name);
}
@Override
public void handelRequest(请假条 request) {
if(request.getDays()<3){
System.out.println("主任审批通过");
}else{
if(this.nextLeader!=null){
this.nextLeader.handelRequest(request);
}
}
}
}
class 经理 extends 领导{
public 经理(String name) {
super(name);
}
@Override
public void handelRequest(请假条 request) {
if(request.getDays()<10){
System.out.println("经理审批通过");
}else{
if(this.nextLeader!=null){
this.nextLeader.handelRequest(request);
}
}
}
}
class 总经理 extends 领导{
public 总经理(String name) {
super(name);
}
@Override
public void handelRequest(请假条 request) {
if(request.getDays()<30){
System.out.println("总经理审批通过");
}else{
if(this.nextLeader!=null){
this.nextLeader.handelRequest(request);
}
}
}
}
--------------------------------------------------------------------------------
public class Client {
public static void main(String[] args) {
领导 a = new 主任("张主任");
领导 b = new 经理("李经理");
领导 c = new 总经理("王总经理");
a.setNextLeader(b);
b.setNextLeader(c);
请假条 leaveRequest = new 请假条("蔡立亮", 2, "病假");
a.handelRequest(leaveRequest);
}
}
--------------------------------------------------------------------------------
结果:
主任审批通过
--------------------------------------------------------------------------------
总结:职责链模式通过把多个处理逻辑对象串在一起,按顺序进行处理,前面处理不了的就丢到后面的处理,这样可以灵活的增减处理过程
二、迭代器模式(Iterator)
2.1、作用:定义一个迭代器,可以方便的对聚合对象进行遍历处理
2.2、UML图:
2.3、示例:
public interface 迭代器接口 {
public void first();//指向第一个对象
public void next();//指向下一个对象
public boolean hasNext();//是否还有对象
public boolean isFirst();//是否是最前一个对象
public boolean isDone();//是否是最后一个对象
public Object currentItem();//当前对象
}
--------------------------------------------------------------------------------
public class 自定义迭代器 implements 迭代器接口{
private List
三、中介者模式(Mediator)
3.1、作用:解耦多个同事对象之间的交互关系。每个对象都持有中介者对象的引用,只跟中介者对象打交道。我们通过中介者对象统一管理这些交互关系
3.2、好处:
3.3、UML图:
3.4、示例:
public interface 部门接口 {
public String getName();//获取部门名称
public void selfAction(部门接口 dept);//内部动作
public void outAction(部门接口 dept);//外部动作
}
class 人事部 implements 部门接口{
private 中介者接口 mediator;
private String name;
public 人事部(String name,中介者接口 mediator) {
super();
this.name = name;
this.mediator = mediator;
}
public String getName() {
return name;
}
public void selfAction(部门接口 dept) {
System.out.println("接到"+dept.getName()+"通知,我们现在就去招人");
}
public void outAction(部门接口 dept) {
mediator.command(this,dept);
}
}
class 财务部 implements 部门接口{
private 中介者接口 mediator;
private String name;
public 财务部(String name,中介者接口 mediator) {
super();
this.name = name;
this.mediator = mediator;
}
public String getName() {
return name;
}
public void selfAction(部门接口 dept) {
System.out.println("接到"+dept.getName()+"通知,我们现在去发工资");
}
public void outAction(部门接口 dept) {
mediator.command(this,dept);
}
}
class 服务部 implements 部门接口{
private 中介者接口 mediator;
private String name;
public 服务部(String name,中介者接口 mediator) {
super();
this.name = name;
this.mediator = mediator;
}
public String getName() {
return name;
}
public void selfAction(部门接口 dept) {
System.out.println("接到"+dept.getName()+"通知,我们现在去服务客户");
}
public void outAction(部门接口 dept) {
mediator.command(this,dept);
}
}
--------------------------------------------------------------------------------
public interface 中介者接口 {
public void regester(部门接口 dept);
public void command(部门接口 dept,部门接口 dept2);
}
--------------------------------------------------------------------------------
public class 中介者 implements 中介者接口{
private Map map = new HashMap();
public void regester(部门接口 dept) {
map.put(dept.getName(), dept);
}
public void command(部门接口 dept,部门接口 dept2) {
dept2.selfAction(dept);
}
}
--------------------------------------------------------------------------------
public class 客户端 {
public static void main(String[] args) {
中介者接口 mediator = new 中介者();
部门接口 cwb = new 财务部("cwb",mediator);
部门接口 rsb = new 人事部("rsb",mediator);
部门接口 fwb = new 服务部("fwb",mediator);
mediator.regester(cwb);
mediator.regester(rsb);
mediator.regester(fwb);
cwb.outAction(rsb);
cwb.outAction(fwb);
}
}
--------------------------------------------------------------------------------
结果:
接到cwb通知,我们现在就去招人
接到cwb通知,我们现在去服务客户
--------------------------------------------------------------------------------
总结:中介者是一个普通对象与中介对象两两相连的关系,即需要相互通信的对象需要持有同一个中介对象,中介对象需要持有所有需要通信的普通对象,这样设计后,如果需要新增普通对象与其它对象通信,就不需要改变原对象代码,只需要新增一个对象,然后在客户端调用时给他设置中介对象,然后把他注册到中介对象即可,满足开闭原则
四、命令模式(Command)
4.1、作用:将一个请求对象封装为一个对象,从而使我们可用不同的请求对客户今次那个参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。也称之为:动作Action模式、事务transaction模式。
4.2、关键结构:Command抽象命令类、ConcreteCommand具体命令类、Invoker调用者/请求者、Receiver接收者、Client客户类。
4.3、UML图:
4.4、示例:
public interface 命令接口 {
public void execute(String command);//执行单个命令
public void executeAll();//执行全部命令
public void addReceiver(命令接收者 r);//增加接受者
public void removeReceiver(命令接收者 r);//删除接收者
public void addCommand(String c);//增加命令
}
--------------------------------------------------------------------------------
public class 命令类 implements 命令接口{
private List<命令接收者> list;
private List commandlist = new ArrayList();
public 命令类() {
super();
this.list = new ArrayList<命令接收者>();
}
public void addReceiver(命令接收者 r) {
list.add(r);
}
public void removeReceiver(命令接收者 r) {
list.remove(r);
}
public void addCommand(String c) {
commandlist.add(c);
}
public void execute(String command) {
for(命令接收者 r : list){
r.play(command);
}
}
public void executeAll() {
for(命令接收者 r : list){
for(String c :commandlist){
r.play(c);
}
}
commandlist.clear();
}
}
--------------------------------------------------------------------------------
public class 命令接收者 {
String name;
public 命令接收者(String name) {
super();
this.name = name;
}
public void play(String command){
System.out.println(name+"执行:"+command);
}
}
--------------------------------------------------------------------------------
public class 命令调用者 {
private 命令接口 command;
public 命令调用者(命令接口 command) {
super();
this.command = command;
}
public void call(String c){
command.execute(c);
}
public void callAll(){
command.executeAll();
}
}
--------------------------------------------------------------------------------
public class 客户端 {
public static void main(String[] args) {
命令接口 command = new 命令类();
command.addReceiver(new 命令接收者("张三"));
command.addReceiver(new 命令接收者("李四"));
command.addReceiver(new 命令接收者("王五"));
命令调用者 invoker = new 命令调用者(command);
invoker.call("起床写代码");
System.out.println("-------------------");
command.addCommand("起床洗脸");
command.addCommand("起床吃早点");
command.addCommand("起床跑步");
invoker.callAll();
}
}
--------------------------------------------------------------------------------
结果:
张三执行:起床写代码
李四执行:起床写代码
王五执行:起床写代码
-------------------
张三执行:起床洗脸
张三执行:起床吃早点
张三执行:起床跑步
李四执行:起床洗脸
李四执行:起床吃早点
李四执行:起床跑步
王五执行:起床洗脸
王五执行:起床吃早点
王五执行:起床跑步
--------------------------------------------------------------------------------
总结:命令模式让命令的执行独立为一个对象,在对象中做命令的调用时,可以对指令进行管理,从而可以实现事务、撤销等功能,但上述例子未达到事务和撤销等目的,一般时配合备忘录模式一起使用才能达到这种效果,本示例只是做到了管理指令,指令批量执行的功能
五、解释器模式(Interpreter)
5.1、介绍:是一种不常用的设计模式,用于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的编译器和解释器设计, 当我们需要开发一种新的语言时,可以考虑使用解释器模式
5.2、UML、示例 略过
六、访问者模式(Visitor)
6.1、作用:表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变个元素的类的前提下定义作用于这些元素的新操作
6.2、使用:略过
七、策略模式(Strategy)
7.1、作用:策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法,并且由客户端决定调用哪个算法。
7.2、UML图:
7.3、示例:
public interface 策略接口 {
public double getPrice(double d);
}
class 钻石会员 implements 策略接口{
public double getPrice(double d) {
return d*0.75;
}
}
class 白金会员 implements 策略接口{
public double getPrice(double d) {
return d*0.85;
}
}
class 普通会员 implements 策略接口{
public double getPrice(double d) {
return d*0.95;
}
}
class 非会员 implements 策略接口{
public double getPrice(double d) {
return d;
}
}
--------------------------------------------------------------------------------
public class 刷卡机 {
private 策略接口 strategy;
public void setStrategy(策略接口 strategy) {
this.strategy = strategy;
}
public void printPrice(double d){
System.out.println(strategy.getPrice(d));
}
}
--------------------------------------------------------------------------------
public class 客户端 {
public static void main(String[] args) {
钻石会员 strategy1 = new 钻石会员();
白金会员 strategy2 = new 白金会员();
普通会员 strategy3 = new 普通会员();
非会员 strategy4 = new 非会员();
刷卡机 pos = new 刷卡机();
System.out.println("-------钻石会员-------");
pos.setStrategy(strategy1);
pos.printPrice(1000);
System.out.println("-------白金会员-------");
pos.setStrategy(strategy2);
pos.printPrice(1000);
System.out.println("-------普通会员-------");
pos.setStrategy(strategy3);
pos.printPrice(1000);
System.out.println("-------非会员-------");
pos.setStrategy(strategy4);
pos.printPrice(1000);
}
}
--------------------------------------------------------------------------------
结果:
-------钻石会员-------
750.0
-------白金会员-------
850.0
-------普通会员-------
950.0
-------非会员-------
1000.0
--------------------------------------------------------------------------------
总结:略
八、模版方法模式(Template method)
8.1、作用:处理某个流程的代码都已经具备但是其中某个节点的代码暂时不能确定。因此,我们采用工厂方法模式,将这个节点的代码实现转移给子类完成。即:处理步骤父类中定义好,具体实现延迟到子类中定义。
8.2、UML图:
8.3、示例:
public abstract class 抽象父类 {
public void 取号(){
System.out.println("排队取号");
}
public abstract void 办业务();
public void 评价(){
System.out.println("给客户评分");
}
public final void 模板(){
this.取号();
this.办业务();
this.评价();
}
}
--------------------------------------------------------------------------------
public class 具体子类 extends 抽象父类 {
@Override
public void 办业务() {
System.out.println("窗口办业务");
}
}
class 具体子类2 extends 抽象父类 {
@Override
public void 办业务() {
System.out.println("柜台办业务");
}
}
--------------------------------------------------------------------------------
public class 客户端 {
public static void main(String[] args) {
抽象父类 templete = new 具体子类();
抽象父类 templete2 = new 具体子类2();
templete.模板();
System.out.println("-----------------");
templete2.模板();
}
}
--------------------------------------------------------------------------------
结果:
排队取号
窗口办业务
给客户评分
-----------------
排队取号
柜台办业务
给客户评分
--------------------------------------------------------------------------------
总结;此模式,针对不同的实现可以有不同的子类实现
九、状态模式(State)
9.1、用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题
9.2、关键组成:Context环境类、State抽象状态类、ConcreteState具体状态类
9.3、UML图:
9.4、示例:
public interface 状态接口 {
public void 行为一();
public void 行为二();
}
--------------------------------------------------------------------------------
public class 空状态 implements 状态接口 {
public void 行为一() {
System.out.println("房间空,可以住人和接受预定");
}
public void 行为二() {
}
}
--------------------------------------------------------------------------------
public class 预定状态 implements 状态接口 {
public void 行为一() {
System.out.println("房间已预定,不可以预定可住人");
}
public void 行为二() {
}
}
--------------------------------------------------------------------------------
public class 已住状态 implements 状态接口 {
public void 行为一() {
System.out.println("房间已住人,不可以预定和住人");
}
public void 行为二() {
}
}
--------------------------------------------------------------------------------
public class 房间 {
private 状态接口 state;
public void setState(状态接口 state) {
this.state = state;
this.state.行为一();
}
}
--------------------------------------------------------------------------------
public class 客户端 {
public static void main(String[] args) {
房间 home= new 房间();
home.setState(new 空状态());
System.out.println("---------------");
home.setState(new 预定状态());
System.out.println("---------------");
home.setState(new 已住状态());
}
}
--------------------------------------------------------------------------------
结果:
房间空,可以住人和接受预定
---------------
房间已预定,不可以预定可住人
---------------
房间已住人,不可以预定和住人
--------------------------------------------------------------------------------
总结:
十、观察者模式(Observer)
10.1、作用:观察者模式主要用于1:N的通知,当对象(目标对象subject)的状态发生变化时,他需要及时的告知一系列的对象(观察者对象observer),令他们做出响应。
10.2、通知观察者的方式:推送、拉取
10.3、UML图:
10.4、示例:
public abstract class 抽象目标对象类 {
protected List<观察者接口> list = new ArrayList<观察者接口>();
public abstract void Notify();//发布消息
public abstract void setAction(String action);//设置消息
public void regester(观察者接口 observer){
list.add(observer);
}
public void remove(观察者接口 observer){
list.remove(observer);
}
}
--------------------------------------------------------------------------------
public class 具体目标对象类A extends 抽象目标对象类 {
private String action;
public void setAction(String action) {
this.action = action;
}
@Override
public void Notify() {
for(观察者接口 o :super.list){
o.play(action);
}
}
}
--------------------------------------------------------------------------------
public class 具体目标对象类B extends 抽象目标对象类 {
private String action;
public void setAction(String action) {
this.action = action;
}
@Override
public void Notify() {
for(观察者接口 o :super.list){
o.play(action);
}
}
}
--------------------------------------------------------------------------------
public interface 观察者接口 {
public void play(String action);
}
--------------------------------------------------------------------------------
public class 观察者A implements 观察者接口 {
private String name;
public 观察者A(String name) {
super();
this.name = name;
}
public void play(String action) {
System.out.println("观察者A("+name+")检测到动作"+action);
}
}
--------------------------------------------------------------------------------
public class 观察者B implements 观察者接口 {
private String name;
public 观察者B(String name) {
super();
this.name = name;
}
public void play(String action) {
System.out.println("观察者B("+name+")检测到动作"+action);
}
}
--------------------------------------------------------------------------------
public class 客户端 {
public static void main(String[] args) {
抽象目标对象类 subject = new 具体目标对象类A();
观察者A observer1 = new 观察者A("蔡立亮1");
观察者A observer2 = new 观察者A("蔡立亮2");
观察者B observer3 = new 观察者B("蔡立亮3");
观察者B observer4 = new 观察者B("蔡立亮4");
subject.regester(observer1);
subject.regester(observer2);
subject.regester(observer3);
subject.regester(observer4);
subject.setAction("开始跑步");
subject.Notify();
}
}
--------------------------------------------------------------------------------
结果:
观察者A(蔡立亮1)检测到动作开始跑步
观察者A(蔡立亮2)检测到动作开始跑步
观察者B(蔡立亮3)检测到动作开始跑步
观察者B(蔡立亮4)检测到动作开始跑步
--------------------------------------------------------------------------------
总结:
十一、备忘录模式(Memento)
11.1、作用:就是保存某个对象内部状态的拷贝,这样以后就可以将该对象恢复到原先的状态
11.2、关键组成:源发器类Originator、备忘录类Memento、负责人类CareTaker
11.2、UML图:
11.3、示例:
public class 员工 {
private String name;
private String position;
private double salary;
private 备忘录 memento = new 备忘录();
public 员工(String name) {
super();
this.name = name;
}
public void createMemento(){
memento.add(new 员工Memento(name,position,salary));
}
public void recovery(){
员工Memento m = memento.get();
this.name = m.getName();
this.position = m.getPosition();
this.salary = m.getSalary();
}
public void print(){
System.out.println("姓名:"+name+";岗位:"+position+";薪水:"+salary);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
--------------------------------------------------------------------------------
public class 员工Memento {
private String name;
private String position;
private double salary;
public 员工Memento(String name, String position, double salary) {
super();
this.name = name;
this.position = position;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
--------------------------------------------------------------------------------
public class 备忘录 {
private Stack<员工Memento> stack = new Stack<员工Memento>();
public void add(员工Memento m){
stack.add(m);
}
public 员工Memento get(){
int len = stack.size();
if(len==1){
return stack.peek();
}else{
return stack.pop();
}
}
}
--------------------------------------------------------------------------------
public class 客户端 {
public static void main(String[] args) {
员工 employee = new 员工("蔡立亮");
employee.setPosition("程序员");
employee.setSalary(8000);
employee.print();
System.out.println("--------------------");
employee.createMemento();
employee.setPosition("项目经理");
employee.setSalary(10000);
employee.print();
employee.createMemento();
employee.setPosition("技术经理");
employee.setSalary(15000);
employee.print();
employee.createMemento();
employee.setPosition("部门经理");
employee.setSalary(20000);
employee.print();
System.out.println("---------撤回-----------");
employee.recovery();
employee.print();
System.out.println("---------撤回-----------");
employee.recovery();
employee.print();
System.out.println("---------撤回-----------");
employee.recovery();
employee.print();
System.out.println("---------撤回-----------");
employee.recovery();
employee.print();
}
}
--------------------------------------------------------------------------------
结果:
姓名:蔡立亮;岗位:程序员;薪水:8000.0
--------------------
姓名:蔡立亮;岗位:项目经理;薪水:10000.0
姓名:蔡立亮;岗位:技术经理;薪水:15000.0
姓名:蔡立亮;岗位:部门经理;薪水:20000.0
---------撤回-----------
姓名:蔡立亮;岗位:技术经理;薪水:15000.0
---------撤回-----------
姓名:蔡立亮;岗位:项目经理;薪水:10000.0
---------撤回-----------
姓名:蔡立亮;岗位:程序员;薪水:8000.0
---------撤回-----------
姓名:蔡立亮;岗位:程序员;薪水:8000.0
--------------------------------------------------------------------------------
总结:这里之所以要一个“员工Memento”类,是因为“员工“类可能不是所有的属性都需要备份,只需要备份部分属性,如果直接备份“员工”类,则显得比较浪费资源