行為型模式
描述程序運(yùn)行時(shí)復(fù)雜的流程控制,涉及算法和對(duì)象間的行為控制。
一、模板方法模式 Template Method
定義算法模板,規(guī)范了基本構(gòu)建,將部分算法延遲到子類進(jìn)行,是的不改變整體結(jié)構(gòu)情況下重新定義算法特定步驟。
13templateMethod.png
抽象類 AbstractClass
- 模板方法:定義算法骨架,按某種順序調(diào)用基本方法。
- 基本方法: 整體算法中的一個(gè)步驟。
- 抽象方法:聲明由子類實(shí)現(xiàn)。
- 具體方法:抽象類實(shí)現(xiàn),子類和集成或重寫。
- 鉤子方法:抽象類已經(jīng)實(shí)現(xiàn),包括用于判斷邏輯方法和需要子類重寫的空方法。
abstract AbstractClass{
void templateMethod(){
specificMethod();
abstractMethod1();
if(Hook1()){
abstractMethod2();
}
}
void specificMethod(){
System.out.println("開始");
}
void abstractMethod1();
void abstractMethod2();
boolean Hook1(){
return true;
}
}
具體子類 ConcreteClass
實(shí)現(xiàn)抽象類中的抽象方法和鉤子方法。
class ConcreteClass extends AbstractClass{
void abstractMethod1(){
System.out.print("method1");
}
void abstractMethod2(){
System.out.print("method2");
}
boolean Hook1(){
return false;
}
}
客戶端 TestTemplate
class TestTemplate {
public static void main(String[] args ){
AbstractClass a=new ConcreteClass();
a.templateMethod();
}
}
二、策略模式 Strategy
定義了一系類算法,并對(duì)算法進(jìn)行封裝使得可以相互替換,算法的替換不影響客戶的調(diào)用。
優(yōu)點(diǎn):避免多重判斷,減少重復(fù)代碼。
可以根據(jù)不同的時(shí)間空間選擇不同算法,算法擴(kuò)展不修改原算法。使用放到環(huán)境類中,算法實(shí)現(xiàn)放到具體策略類中,二者分離。
缺點(diǎn):客戶需要了解算法使用條件,增加很多策略類。

抽象策略類 Strategy
interface Strategy{
void strateyMethod();
}
具體策略類 ConcreteStrategy
class ConcreteStrategyA{
void strategyMethod(){
System.out.println("strategyA");
}
}
class ConcreteStrategyB{
void strategyMethod(){
System.out.println("strategyB);
}
}
環(huán)境類 Context
class Context{
private Strategy strategy;
Strategy getStrategy(){
return strategy;
}
void setStrategy(Strategy strategy){
this.strategy=strategy;
}
void strategyMethod(){
strategy.strategyMethod();
}
}
客戶端 StrategyPatternTest
class StrategyPatternTest{
public static void main(String[] args){
Context ct=new Context();
ct.setStrategy(new ConcreteStrategyA());
ct.strategyMethod();
}
}
擴(kuò)展策略工廠 StrategyFactory
class StrategyFactory{
Map<String,Strategy> stf=new HashMap<>();
void put(String key,Strategy strategy){
stf.put(key,strategy);
}
Strategy getStrategy(String key){
return stf.get(key);
}
void strategyMethod(String key){
stf.get(key).strategyMethod();
}
}
三、命令模式 Command
將請(qǐng)求封裝成對(duì)象,是的發(fā)出請(qǐng)求的責(zé)任和處理請(qǐng)求的責(zé)任分離。
優(yōu)點(diǎn): 降低耦合度,擴(kuò)展靈活,可以實(shí)現(xiàn)宏命令,方便實(shí)現(xiàn)Undo,Redo操作。
缺點(diǎn):增加大量的命令類,增加復(fù)雜性。

抽象命令 Command
abstract Command{
void execute();
}
具體命令 ConcreteCommand
class ConcreteCommand implements Command{
private ReceiverA receiverA;
public ConcreteCommand(){
receiverA=new ReceiverA();
}
void execute(){
receiverA.action();
}
}
命令接收者 Receiver
class Receiver{
void action(){
System.out.println("acionA");
}
}
調(diào)用者 invoker
class Invoker{
private Command command;
public Invoker(Command command){
this.command=command;
}
public void setCommand(Command command){
this.command=command;
}
public void call(){
command.execute();
}
}
客戶端 TestCommandPattern
class TestCommandPattern{
public static void main(){
Command commandA= new ConcreteCommandA();
Invoker invoker=new Invoker(commandA);
invoker.call();
}
}
命令模式擴(kuò)展
配合組合模式,構(gòu)成宏命令模式,也即組合命令模式
class CompositeInvoker implements AbstractCommand{
private ArrayList<AbstractCommand> children =new ArraryList<>();
public void add(AbstractCommand a){
children.add(a);
}
public void remove(AbstractCommand a){
children.remove(a);
}
public AbstractCommand getChild(int i){
return children.get(i);
}
public void execute(){
for(Object obj:children){
obj.execute();
}
}
}
四、責(zé)任鏈(職責(zé)鏈模式) Chain of Responsibility
為了避免請(qǐng)求發(fā)送者與多個(gè)請(qǐng)求處理著耦合在一起,將多有請(qǐng)求的處理著通過前一個(gè)對(duì)象的引用而連城一條鏈。請(qǐng)求發(fā)生時(shí)沿著鏈傳遞,直到處理為止。

抽象處理者角色 Handler
abstract Handler{
private Handler next;
public void setNext(Handler handler){
this.next=handler;
}
public Handler getNext(){
return next;
}
void handlerRequest();
}
具體處理角色 ConcreteHandler
class ConcreteHandlerA implements Handler{
void handlerRequest(String rq){
if("A".equal(rq)) System.out.println("處理");
else{
getNext().handlerRequest(rq);
}
}
}
class ConctreteHandlerB implements Handler{
void handlerRequest(String rq){
if("B".equal(rq))
System.out.println("B");
else{
getNext().handlerRequest(rq);
}
}
}
客戶類 Client
創(chuàng)建處理鏈,并向鏈頭的具體處理者對(duì)象提交請(qǐng)求。
publict TestChainofResponsibility{
public static void main(String[] args){
Handler handler=new ConcreteHandlerA();
Handler handlerB=new ConcreteHandlerB();
handler.setNext(HandlerB);
handler.handlerRequest("B");
}
}
模式的擴(kuò)展
- 純的職責(zé)鏈模式
- 不純的職責(zé)鏈模式:一個(gè)請(qǐng)求必須被某一個(gè)處理者對(duì)象接收。接收后兩種處理一種自己處理或推給下家。
- 允許出現(xiàn)某一個(gè)具體處理者對(duì)象在承擔(dān)部分責(zé)任后,將其他責(zé)任傳給下架的情況。

五、狀態(tài)模式 State
對(duì)有狀態(tài)的對(duì)象,把復(fù)雜的判斷邏輯提取到不同的狀態(tài)對(duì)象中,允許狀態(tài)對(duì)象在其內(nèi)部狀態(tài)改變是改變行為。
環(huán)境角色 Context
class Context{
private State state;
Pulic void Context(State state){
this.state=new ConcreteStateA();
}
Public void Handle(){
state.Handle(this);
}
public void setState(State state){
this.state = state;
}
public State getState(){
return state;
}
}
抽象狀態(tài)類 State
abstract State{
void handle(Context context);
}
具體狀態(tài)類 ConcreteState
class ConcreteStateA extends State{
void Handle(Context context){
System.out.println("A");
context.setState(new ConcreteStateB());
}
}
class ConcreteStateB extends State{
void handle(Context context){
System.out.println("B");
context.setState(new ConcreteStateA());
}
}
客戶端 TestState
class TestState{
public static void(String[] args){
Context ct=new Context();
ct.handle("A");
ct.handle("B");
ct.handle("C");
}
}
狀態(tài)模式擴(kuò)展
有些情況可能多個(gè)環(huán)境共享一組狀態(tài),這時(shí)候需要引入享元模式,狀態(tài)放到集合中程序共享。
class ShareContext{
private ShareState state;
private HashMap<String,ShareState> stateSet =new HashMap<>();
public ShareContext(){
state=new ConcreteState1();
stateSet.put("1",state);
state=new ConcreteState2();
stateSet.put("2",state);
state=getState("1");
}
public void setState(ShareState state){
this.state=state;
}
public ShareState getState(String key){
ShareState s= (ShareState)stateSet.get(key);
return s;
}
public void Handle(){
state.handle(this);
}
}
六、觀察者模式
多個(gè)對(duì)象間存在一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變是其它對(duì)象自動(dòng)更新,這種模式有時(shí)候又稱作發(fā)布-訂閱模式。在軟件開發(fā)中用的最多的是窗體程序設(shè)計(jì)中的事件處理,sping 中ApplicationContext 的事件機(jī)制也是通過該模式實(shí)現(xiàn)的。
優(yōu)點(diǎn): 降低了目標(biāo)與觀察者之間的耦合關(guān)系。目標(biāo)與觀察者之間建立了一套觸發(fā)機(jī)制。
缺點(diǎn):目標(biāo)和觀察者之間的醫(yī)療沒有完全解除,可能導(dǎo)致循環(huán)引用。 當(dāng)觀察者對(duì)象很多時(shí),通知觀察者會(huì)花費(fèi)很多時(shí)間,影響效率。
20observer.png
抽象主題 Subject
保存觀察者對(duì)象的聚集類和增刪方法,通知所有觀察者。
abstract Subject{
private List<Observer> observers=new ArraryList<>();
public void add(Observer obs){
if(observers.contains(obs))return;
observers.add(obs);
}
public void remove(Observer obs){
observers.remove(obs);
}
public void notifyObserver();
}
具體主題 ConcreteSubject
class ConcreteSubject extends Subject{
public void notifyObserver(){
for(Observer obs:observers){
obs.response();
}
}
}
抽象觀察者 Observer
interface Observer{
void response();
}
具體觀察者 ConcreteObserver
class ConcreteObserver1 implements Observer{
void response(){
System.out.println("觀察者1");
}
}
class ConcreteObserver2 implements Observer{
void response(){
System.out.println("觀察者2");
}
}
客戶端 TestObserver
class TestObserver{
public static void main(String[] args){
Subject subject =new ConcreteSubject();
Observer obs1=new ConcreteObserver1();
subject.add(obs1);
Observer obs2= new ConcreteObserver2();
subject.add(obs2);
subject.notifyObserver();
}
}
模式擴(kuò)展
在java中,通過java.util.Observable類和 java.util.Observer 接口定義觀察者模式。
1、Observable類
- 抽象目標(biāo)類,有一個(gè)Vector向量,用于保存需要通知的觀察者對(duì)象
- void addObserver(Observer o) 添加觀察者
- void notifyObservers(Object arg) 調(diào)用向量中觀察者對(duì)象update方法
,越晚加入越先得到通知 - void setChange() 用于設(shè)置內(nèi)部標(biāo)志位,為真時(shí)notifyObservers才會(huì)通知觀察者。
2、Observer接口
抽象觀察者,監(jiān)視目標(biāo)的變化。
具體目標(biāo)觀察者
class MdmMapping extends Observable{
public void changeMapping(MdmMap mp){
super.setChanged();
super.notifyObservers(mp);
}
}
觀察者
class CacheMapping implements Observer{
public void update(Observable o,Object arg){
MdmMap mdmMap=(MdmMap)arg;
Cache.remove(arg.getKey());
}
}
class DbMapping implements Observer{
public void update(Observable o,Object arg){
MdmMap mdmMap=(MdmMap)arg;
Mappingdb.update(mdmMap);
}
}
調(diào)用類
public class MappingTest{
public static void main(String[] args){
MdmMapping mdmMp=new MdmMapping();
Observer cache=new CacheMapping();
Observer db =new DbMapping();
mdmMp.addObserver(cache);
mdmMp.addObserver(db);
MdmMap mp=new MdmMap();
mp.setkey("1");
mp.setvalue("男");
mdmMp.changeMapping(mp);
}
}
七、中介者mediator
定義一個(gè)中介對(duì)象來封裝一系列對(duì)象之間的交互
優(yōu)點(diǎn):
- 降低對(duì)象間耦合,使得對(duì)象可以獨(dú)立復(fù)用
- 對(duì)象間一對(duì)多的關(guān)系轉(zhuǎn)變?yōu)橐粚?duì)一,提高系統(tǒng)靈活性

抽象中介者 Mediator
定義了注冊(cè)和轉(zhuǎn)發(fā)的接口
abstract class Mediator{
public abstract void register(Colleague colleagur);
public abstract void relay(Colleague cl);
}
具體中介者 ConcreteMediator
class ConcreteMediator extands Mediator{
private List<Colleague> colleagues= new ArrayList<>();
public void register(Colleague colleague){
if(!colleagues.contains(colleague)){
colleagues.add(colleague);
colleague.setMedium(this);
}
}
pulic void relay(Colleague cl){
for(Colleague ob:colleagues){
if(!ob.equals(cl)){
((Colleague)ob).receive();
}
}
}
}
抽象同事類 Colleague
abstract class Colleague{
protected mediator mediator;
public void setMedium(Mediator mediator){
this.mediator=mediator;
}
public abstract void receive();
public abstract void send();
}
具體同事類 ConcreteColleague
class ConcreteColleague1 extends Colleague{
public void receive(){
System.out.println("接收請(qǐng)求");
}
public void send(){
System.out.println("發(fā)送請(qǐng)求");
mediator.relay(this);
}
}
class ConcreteColleague2 extends Colleague{
public void receive(){
System.out.println("接收請(qǐng)求");
}
public boid send(){
System.out.println("發(fā)送請(qǐng)求");
mediator.relay(this);
}
}
八、迭代器 Iterator
提供一個(gè)對(duì)象來訪問聚合對(duì)象中的一系列數(shù)據(jù),而不暴露聚合對(duì)象的內(nèi)部表示。聚合迭代非常密切,大多數(shù)語言在實(shí)現(xiàn)聚合類是都提供了迭代類。
- 當(dāng)需要為聚合對(duì)象提供多種遍歷方式時(shí)。
- 為遍歷不同聚合結(jié)構(gòu)提供統(tǒng)一的接口。
- 訪問聚合對(duì)象而無需暴露內(nèi)部細(xì)節(jié)時(shí)。

抽象聚合 Aggregate
定義存儲(chǔ)、添加、刪除聚合對(duì)象以及創(chuàng)建迭代器對(duì)象接口。
interface Aggregate{
public void add(Object o);
public void remove(Object o);
public Iterator getInterator();
}
具體迭代器 ConcreteAggregate
class ConcreteAggregate implements Aggregate{
private List<Object> list =new ArrayList<>();
public void add(Object o){
list.add(o);
}
public void remove(Object o){
list.remove(o);
}
public Iterator getIterator(){
return (new ConcreteIterator(list));
}
}
抽象迭代器 Iterator
定義訪問和遍歷聚合元素的接口,通常包括hasNext()、first()、next()等方法。
interface Iterator{
public boolean hasNext();
public Object first();
public Object next();
}
具體迭代器 ConcreteIterator
class ConcreteIterator implements Iterator{
private List<Object> list=null;
private int index=-1;
public ConcreteIterator(List<Object> list){
this.list=list;
}
public boolean hasNext(){
if(index<list.size()-1){
return true;
}else{
return false;
}
}
public Object first(){
index=0;
Object obj=list.get(index);
return obj;
}
public Object next(){
Object obj=null;
if(this.hasNext()){
obj=list.get(++index);
}
return obj;
}
}
模式的擴(kuò)展
迭代器常常與組合模式結(jié)合起來使用,經(jīng)常潛藏在組合模式的容器構(gòu)成類中。
class Composite impelements Component{
private List<Component> components= new Arrarylist<>();
public void add(Commponent com){
components.add(com);
}
public void remove(Commponent com){
components.remove(com);
}
public Commponent getChild(int i){
return components.get(i);
}
public void Operation(){
System.out.println("opt");
}
public Iterator getIterator(){
return (new ConcreteIterator(components));
}
}
九、訪問者模式 Visitor
將作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素操作分離成獨(dú)立的類,使得在不改變數(shù)據(jù)機(jī)構(gòu)的前提下添加新的操作,為數(shù)據(jù)結(jié)構(gòu)中的元素提供各種操作。數(shù)據(jù)元素和數(shù)據(jù)操作分離,是行為模式中最復(fù)雜的一種模式。
21visitor.png
抽象訪問者 Visitor
為每個(gè)對(duì)應(yīng)元素提供一個(gè)訪問操作visit(),參數(shù)標(biāo)識(shí)了被訪問元素
interface Visitor{
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
具體訪問者 ConcreteVisitor
class ConcreteVisitorA implements Visitor{
void visitor(ConcreteElementA element){
System.out.println("具體訪問者A訪問->"+element.operationA());
}
void visitor(ConcreteElementB element){
System.out.println("A->"+element.operationB());
}
}
抽象元素 Element
interface Element{
void accept(Visitor visitor);
}
具體元素 ConcreteElement
class ConcreteElementA implements Element{
void accept(Visitor v){
v.visit(this);
}
String operationA(){
return "ConcreteElementA";
}
}
class ConcreteElementB implements Element{
void accept(Visitor v){
v.visit(this);
}
String operationB(){
return "ConcreteElementB";
}
}
對(duì)象結(jié)構(gòu) ObjectStruct
包含元素角色的容器,提供訪問者訪問元素
class ObjectStruct {
private List<Element> elements=new ArrayList<>();
public void accept(Visitor visitor){
Iterator<Element> i=list.iterator();
while(i.hasNext()){
((Elemnet)i.next()).accept(visitor);
}
}
public void add(Element element){
list.add(element);
}
public void remove(Element element){
list.remove(element);
}
}
客戶端調(diào)用 TestVisitor
public class TestVisitor{
public static void main(String[] args){
ObjectStrut objects=new ObjectStrut();
ConcreteElementA cA=new ConcreteElementA();
COncreteElementB CB=new ConcreteElementB();
objects.add(cA);
objects.add(cB);
Visitor vA=new ConcreteVisitorA();
Visitor vB=new ConcreteVisitorB();
objects.accept(vA);
objects.accept(vB);
}
}
模式擴(kuò)展
訪問這模式使用頻率比較高的一種模式,通常與迭代器或組合模式聯(lián)用。
以組合模式為例(主要具體元素類):
葉子構(gòu)件 Leaf
class ConcreteLeafElement implements Element{
void accept(Visitor v){
v.visit(this);
}
void operatorLeaf(){
System.out.print("leaf");
}
}
樹枝構(gòu)件Composite
class CompositeElement implements Element{
private List<Element> elements=new ArrayList<>();
void accept(Visitor v){
for(Element e:elements){
v.visit(e);
}
}
void operatorComposite(){
System.out.print("Composite");
}
void add(Element e){
elements.add(e);
}
void remove(Element e){
elements.remove(e);
}
Element getChild(int i){
elements.get(i);
}
}
十、備忘錄模式 Memento
在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài),以便以后當(dāng)需要的時(shí)能將該對(duì)象恢復(fù)到原先保存的狀態(tài)。又叫快照模式。

備忘錄Memento
class Memento{
private String state;
public Memento(String state){
this.state=state;
}
public void setState(String state){
this.state=state;
}
public String getState(){
return state
}
}
發(fā)起人Originator
記錄當(dāng)前時(shí)刻的內(nèi)部狀態(tài)信息,提供創(chuàng)建備忘錄和恢復(fù)備忘錄數(shù)據(jù)的功能,實(shí)現(xiàn)其他業(yè)務(wù)功能,可以訪問備忘錄里的所有信息。
class Originator{
private String state;
public void setState(String state){
this.state=state;
}
public String getState(){
return state;
}
public Memento createMemento(){
return new Memento(state);
}
public void restoreMemento(Memento m){
this.setState(m.getState());
}
}
管理者 Caretaker
class Caretaker{
private Memento memento;
public void setMemento(Memento m){
memento=m;
}
public Memento getMemento(){
return memento;
}
}
客戶端 TestMemento
public class TestMemento{
public static void main(String[] args){
Originator otr=new Originator();
Caretaker ctr=new Caretaker();
otr.setState("1");
ctr.setMemento(otr.createMemento());
otr.setState("2");
otr.restoreMemento(ctr.getMemento());
}
}
模式擴(kuò)展
和原型模式結(jié)合使用,可以擁有自備功能,省去了備忘錄,主要變化在發(fā)起人。
class OriginatorPrototype implements Cloneable{
private String state;
public void setState(String state){
this.state=state;
}
public String getState(){
return state;
}
public OriginatorPrototype createMemento(){
return this.clone();
}
public void restoreMemento(OriginatorPrototype opt){
this.setState(opt.getState());
}
public OriginatorPrototype clone(){
try{
return(OriginatorPrototype) super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return null;
}
}
十一、解釋器模式 Interpreter
給分析對(duì)象定義一個(gè)語言,并定義該語言的文法表示,在設(shè)計(jì)一個(gè)解釋器來解釋語言中的句子。該模式實(shí)現(xiàn)了文法表達(dá)式處理的接口,該接口解釋一個(gè)特定的上下文。
- 優(yōu)點(diǎn): 擴(kuò)展性好,可通過集成改變或擴(kuò)展語法。 每個(gè)表達(dá)式都是類似的實(shí)現(xiàn)比較容易。
- 缺點(diǎn):解析器模式中通常使用大量的循環(huán)和遞歸調(diào)用,當(dāng)解釋的句子復(fù)雜時(shí),運(yùn)行速度很慢,且調(diào)試代碼比較麻煩。
解釋器模式通常用于對(duì)簡單語言的編譯或分析實(shí)例中,為了掌握好他的結(jié)構(gòu)和實(shí)現(xiàn),必須先了解編譯原理中的“we文法、句子、語法樹”等相關(guān)概念。

抽象表達(dá)式 Abstract Expression
interface AbstractExpression{
public Object interpret(String info);
}
終結(jié)符表達(dá)式 Terminal Expression
class TerminalExpressoin implements AbstractExpression{
private Set<String> set=new HashSet<String>();
public boolean interpret(String info){
if(set.contains(info)){
return true;
}
return false;
}
public TerminalExpression(String[] data){
for(int i=0;i<data.length;i++)set.add(data[i]);
}
}
非終結(jié)符表達(dá)式 Nonterminal Expression
class NonterminalExpression implements AbstractExpression{
private AbstractExpression city;
private AbstractExpression person;
public AndExpression(Expression city,Expression person){
this.city=city;
this.person=person;
}
public boolean interpret(String info){
String s[]=info.split("的");
return city.interpret(s[0])&&persion.interpret([s[1]);
}
}
環(huán)境 Context
class Context{
private String[] citys={"韶關(guān)","廣州"};
private String[] persons={"老人","婦女","兒童"};
private Expression cityPerson;
public Context(){
Expression city=new TerminalExpression(citys);
Expression person=new TerminalExpression(persons);
cityPerson=new AndExpression(city,person);
}
pulic void freeRide(String info){
boolean ok =cityPerson.interpret(info);
if(ok) System.out.println("免費(fèi)");
else System.out.println("扣費(fèi)2元");
}
}
客戶端 TestInterpret
public class InterpreterPattern{
public static void main(String[] args){
Context bus=new Context();
bus.freeRide("廣東的婦女");
bus.freeRide("韶關(guān)的年輕人");
}
}
模式擴(kuò)展
項(xiàng)目開發(fā)中,如果要對(duì)表達(dá)式進(jìn)行分析計(jì)算,java提供了數(shù)學(xué)公式解析器: Expression4J、Jep等


