23種設計模式Java版第六篇

ps:本文系轉載文章,閱讀原文可獲取源碼,文章末尾有原文連接編程

ps:這一篇是寫迭代器模式、責任鏈模式和命令模式架構

一、迭代器模式ide

提供一個對象來順序訪問聚合對象中的一堆數據,同時也隱藏聚合對象的內部表示;Java 中的 Collection、List、Set、Map 等就用到了迭代器模式。測試

迭代器模式具備如下幾種角色:this

(1)抽象聚合角色:建立迭代器對象的接口,通常含有添加、刪除聚合對象等方法。設計

(2)具體聚合角色:實現抽象聚合角色,獲得一個具體迭代器的對象。日誌

(3)抽象迭代器角色:遍歷聚合元素的接口或者抽象類,通常含 hasNext 等方法。code

(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 的數據進行遍歷。

迭代器模式能夠訪問一個隱藏內部表示的聚合對象的內容,遍歷數據由迭代器來實現,在代碼上必定程度簡化了聚合類;它能夠用不一樣方式訪問一個聚合,也能夠訪問自定義迭代器子類的數據;運用了封裝性,爲不一樣的具體聚合類提供一個統一的接口;可是新增一個具體聚合類或者具體迭代器類,在必定程度上使用可能會複雜。

二、責任鏈模式

把全部請求的處理者經過前一對象的屬性引用下一個對象而造成一條鏈,當有請求時,請求沿着這條鏈進行傳遞,直到有條件知足時就會有對象處理它。

責任鏈模式包含如下角色:

(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 審批,員工「小六」也是同樣的道理。

責任鏈模式下降了對象之間的耦合度,加強了系統的可擴展性,加強了給對象指派職責的靈活性,責任鏈簡化了對象之間的鏈接,分擔了責任;可是它不能保證每一個請求必定被處理,若是是比較長的職責鏈,請求的處理也許涉及多個處理對象,客戶端這邊要理清責任鏈的關係,給程序增長了必定的複雜性。

三、命令模式

將一個執行請求封裝爲一個對象,目的是爲了發出請求的責任和執行請求的責任分開來,它們之間經過命令對象進行通訊,這樣就更好的對命令對象進行管理等。

命令模式包含如下幾個角色:

(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 方法。

命令模式能夠下降對象之間的耦合度,新的命令也很容易地加入到系統中,能夠很容易地設計一個組合命令,調用同一接口命令的方法能夠實現不一樣的功能 ;可是極可能產生大量具體的命令類,以命令的形式進行架構、解耦請求和實現,引入了額外的類型結構,在理解上添加了必定的難度。

相關文章
相關標籤/搜索