乐趣区

关于java:23种设计模式Java版第六篇

ps:本文系转载文章,浏览原文可获取源码,文章开端有原文链接

ps:这一篇是写迭代器模式、责任链模式和命令模式

1、迭代器模式

提供一个对象来程序拜访聚合对象中的一堆数据,同时也暗藏聚合对象的外部示意;Java 中的 Collection、List、Set、Map 等就用到了迭代器模式。

迭代器模式具备以下几种角色:

(1)形象聚合角色:创立迭代器对象的接口,个别含有增加、删除聚合对象等办法。

(2)具体聚合角色:实现形象聚合角色,失去一个具体迭代器的对象。

(3)形象迭代器角色:遍历聚合元素的接口或者抽象类,个别含 hasNext 等办法。

(4)具体迭代器角色:实现形象迭代器角色中所定义的形象办法,并放弃迭代过程中的游标位置。

上面用代码举个例子:

(1)形象迭代器角色,新建一个 MyIterator 接口:

public interface MyIterator {

public void first();
public void next();
public boolean hasNext();
public boolean isFirst();
public boolean isLast();
public Object getCurrentObject();

}

(2)具体迭代器角色,新建一个 ConcreteIterator 类并实现 MyIterator 接口:

public class ConcreteIterator implements MyIterator{
private int cursor;

private WeakReference<List<Object>> wr;

public ConcreteIterator(List<Object> list) {

wr = new WeakReference<List<Object>>(list);

}
@Override
public void first() {

cursor = 0;

}

@Override
public void next() {

if (cursor < size()) {cursor++;}

}
private int size() {

return wr.get().size();

}

@Override
public boolean hasNext() {

if (cursor < size()) {return true;}
return false;

}

@Override
public boolean isFirst() {

return cursor == 0?true:false;

}

@Override
public boolean isLast() {

return cursor == (size()-1)?true:false;

}

@Override
public Object getCurrentObject() {

return wr.get().get(cursor);

}

}

(3)形象聚合角色,新建一个 IAggregate 接口:

public interface IAggregate {
public void addObject(Object object);
public void removeObject(Object object);
public MyIterator createIterator();
}

(4)具体聚合角色,新建一个 ConcreteMyAggregate 类并实现 IAggregate 接口:

public class ConcreteMyAggregate implements IAggregate{

private List<Object> list = new ArrayList<Object>();
@Override
public void addObject(Object object) {this.list.add(object);
}
@Override
public void removeObject(Object object) {this.list.remove(object);
}
@Override
public MyIterator createIterator() {return new ConcreteIterator(list);
}

}

(5)客户端进行调用测试:

IAggregate aggregate = new ConcreteMyAggregate();
aggregate.addObject(“ 公众号小二玩编程 ”);
aggregate.addObject(“bb”);
aggregate.addObject(“cc”);
aggregate.addObject(“dd”);
MyIterator iterator = aggregate.createIterator();
while (iterator.hasNext()) {

String msg = "遍历数据 ----" + iterator.getCurrentObject();
System.out.println(msg);
iterator.next();

}

日志打印如下所示:

图片

首先创立一个具体的聚合角色 ConcreteMyAggregate 实例并向上转型赋值给形象聚合角色 IAggregate,通过聚合角色 aggregate 增加数据并创立一个具体的迭代器角色 ConcreteIterator 实例并向上转型赋值给形象迭代器角色 MyIterator,通过迭代器模式对 iterator 的数据进行遍历。

迭代器模式能够拜访一个暗藏外部示意的聚合对象的内容,遍历数据由迭代器来实现,在代码上肯定水平简化了聚合类;它能够用不同形式拜访一个聚合,也能够拜访自定义迭代器子类的数据;使用了封装性,为不同的具体聚合类提供一个对立的接口;然而新增一个具体聚合类或者具体迭代器类,在肯定水平上应用可能会简单。

2、责任链模式

把所有申请的解决者通过前一对象的属性援用下一个对象而造成一条链,当有申请时,申请沿着这条链进行传递,直到有条件满足时就会有对象解决它。

责任链模式蕴含以下角色:

(1)形象解决者角色:定义出一个解决申请的接口或者抽象类,它必须蕴含一个解决申请的形象办法,最好再多写 2 个办法,用于设置援用下一个对象和返回下一个对象。

(2)具体解决者角色:重写形象解决者角色解决申请的形象办法,在该办法中进行条件筛选,符合条件就进行呈现,否则将申请传给援用的下一个对象进行解决。

上面咱们举个例子,某一个公司的销假流程,销假少于 3 天则由主管审批,销假大于等于 3 天小于 10 天就由副经理审批,销假大于等于 10 天小于 30 天由总经理审批;假如张三是主管,李四是副经理,王五是总经理,张三的领导是李四,李四的领导是王五;用代码实现一下:

(1)形象解决者角色,新建一个抽象类 Leader:

public abstract class Leader {
protected String name;
protected Leader nextLeader;
public Leader(String name) {

super();
this.name = name;

}
public Leader getNextLeader() {

return nextLeader;

}
public void setNextLeader(Leader nextLeader) {

this.nextLeader = nextLeader;

}
public abstract void handleRequest(LeaveRequest l);
}

(2)具体解决者角色,新建一个 Director 类并继承 Leader:

public class Director extends Leader{

public Director(String name) {

super(name);

}

@Override
public void handleRequest(LeaveRequest l) {

if (l.getDay() < 3) {System.out.println("员工:" +l.getName() + ", 销假天数:" + l.getDay() + ", 理由" + l.getReason());
  System.out.println("主任:" + this.name + "审批通过");
} else {if (this.getNextLeader() != null) {this.getNextLeader().handleRequest(l);
  }
}

}

}

(3)具体解决者角色,新建一个 Manager 类并继承 Leader:

public class Manager extends Leader{

public Manager(String name) {

super(name);

}

@Override
public void handleRequest(LeaveRequest l) {

if (l.getDay() < 10) {System.out.println("员工:" +l.getName() + ", 销假天数:" + l.getDay() + ", 理由" + l.getReason());
  System.out.println("经理:" + this.name + "审批通过");
} else {if (this.getNextLeader() != null) {this.getNextLeader().handleRequest(l);
  }
}

}

}

(4)具体解决者角色,新建一个 GaneralManager 类并继承 Leader:

public class GaneralManager extends Leader{

public GaneralManager(String name) {

super(name);

}

@Override
public void handleRequest(LeaveRequest l) {

if (l.getDay() < 30) {System.out.println("员工:" +l.getName() + ", 销假天数:" + l.getDay() + ", 理由" + l.getReason());
  System.out.println("总经理:" + this.name + "审批通过");
} else {System.out.println("你到职吧");
}

}

}

(5)客户端进行测试调用:

    Leader a = new Director("张三");
    Leader b = new Manager("李四");
    Leader c = new GaneralManager("王五");
    a.setNextLeader(b);
    b.setNextLeader(c);
    LeaveRequest lr = new LeaveRequest("小二", 16, "娶老婆");
    LeaveRequest lr2 = new LeaveRequest("小六", 31, "去相亲");
    a.handleRequest(lr);
    a.handleRequest(lr2);

日志打印如下所示:

图片

“把所有申请的解决者通过前一对象的属性援用下一个对象而造成一条链”这句话在这个案例中是这样了解的,a 的 Leader 属性援用的是 b,b 的 Leader 属性援用的是 c;有一个员工“小二”销假 16 天,a 和 b 都审批不了,所以交给 c 审批,员工“小六”也是一样的情理。

责任链模式升高了对象之间的耦合度,加强了零碎的可扩展性,加强了给对象指派职责的灵活性,责任链简化了对象之间的连贯,分担了责任;然而它不能保障每个申请肯定被解决,如果是比拟长的职责链,申请的解决兴许波及多个解决对象,客户端这边要理清责任链的关系,给程序减少了肯定的复杂性。

3、命令模式

将一个执行申请封装为一个对象,目标是为了发出请求的责任和执行申请的责任离开来,它们之间通过命令对象进行通信,这样就更好的对命令对象进行治理等。

命令模式蕴含以下几个角色:

(1)形象命令类角色:定义一个执行命令的接口,蕴含了一个执行命令的形象办法。

(2)具体命令类角色:形象命令类的子类也是具体实现类,它外部援用接收者角色,它的实现办法调用接收者角色执行申请的办法。

(3)接收者角色:是具体命令对象业务的真正实现者。

(4)请求者角色:申请的发送者,通过拜访命令对象来执行相干申请,间接的拜访接收者。

上面用代码举个例子:

(1)形象命令类角色,写一个 Command 接口:

public interface Command {

public void execute();

}

(2)接收者角色,写一个 Receiver 类:

public class Receiver {

public void ation() {System.out.println("Receiver.action");
}

}

(3)具体命令类角色,写一个 ConcreteCommand 类并实现 Command 接口:

class ConcreteCommand implements Command {

private Receiver receiver;
public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}
@Override
public void execute() {receiver.ation();
}

}

(4)请求者角色,写一个 Invoke 类:

public class Invoke {
private Command command;
public Invoke(Command command) {

this.command = command;

}
public void call() {

command.execute();

}
}

(5)客户端进行测试调用:

    Command command = new ConcreteCommand(new Receiver());
    Invoke invoke = new Invoke(command);
    invoke.call();

日志打印如下所示:

图片

在这里 ConcreteCommand 是具体命令类角色对象,它封装了接管类角色对象 Receiver;Invoke 是请求者角色对象,它封装了命令类对象 Command;当 Invoke 发出请求时(调用 call 办法),它的 call 办法调用了 Command 的 execute 办法,而 Command 的 execute 办法又调用了 Receiver 的 ation 办法。

命令模式能够升高对象之间的耦合度,新的命令也很容易地退出到零碎中,能够很容易地设计一个组合命令,调用同一接口命令的办法能够实现不同的性能;然而很可能产生大量具体的命令类,以命令的模式进行架构、解耦申请和实现,引入了额定的类型构造,在了解上增加了肯定的难度。

退出移动版