设计模式-行为型模式

行为型模式

描述程序运行时复杂的流程控制,涉及算法和对象间的行为控制。

一、模板方法模式 Template Method

定义算法模板,规范了基本构建,将部分算法延迟到子类进行,是的不改变整体结构情况下重新定义算法特定步骤。


13templateMethod.png

抽象类 AbstractClass

  • 模板方法:定义算法骨架,按某种顺序调用基本方法。
  • 基本方法: 整体算法中的一个步骤。
    • 抽象方法:声明由子类实现。
    • 具体方法:抽象类实现,子类和集成或重写。
    • 钩子方法:抽象类已经实现,包括用于判断逻辑方法和需要子类重写的空方法。
abstract AbstractClass{
    void templateMethod(){
        specificMethod();
        abstractMethod1();
        if(Hook1()){
            abstractMethod2();
        }
    }
    void specificMethod(){
            System.out.println("开始");
        }
    void abstractMethod1();
    void abstractMethod2();
    boolean Hook1(){
        return true;
    }
}

具体子类 ConcreteClass

实现抽象类中的抽象方法和钩子方法。

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

定义了一系类算法,并对算法进行封装使得可以相互替换,算法的替换不影响客户的调用。
优点:避免多重判断,减少重复代码。
可以根据不同的时间空间选择不同算法,算法扩展不修改原算法。使用放到环境类中,算法实现放到具体策略类中,二者分离。
缺点:客户需要了解算法使用条件,增加很多策略类。

14strategy.png

抽象策略类 Strategy

interface Strategy{
    void strateyMethod();
}

具体策略类 ConcreteStrategy

class ConcreteStrategyA{
    void strategyMethod(){
        System.out.println("strategyA");
    }
}
class ConcreteStrategyB{
    void strategyMethod(){
        System.out.println("strategyB);
    }
}

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

扩展策略工厂 StrategyFactory

class StrategyFactory{
    Map 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

将请求封装成对象,是的发出请求的责任和处理请求的责任分离。
优点: 降低耦合度,扩展灵活,可以实现宏命令,方便实现Undo,Redo操作。
缺点:增加大量的命令类,增加复杂性。

15command.png

抽象命令 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");
    }
}

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

命令模式扩展

配合组合模式,构成宏命令模式,也即组合命令模式

class CompositeInvoker implements AbstractCommand{
    private ArrayList 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();
        }
    }
}

四、责任链(职责链模式) Chain of Responsibility

为了避免请求发送者与多个请求处理着耦合在一起,将多有请求的处理着通过前一个对象的引用而连城一条链。请求发生时沿着链传递,直到处理为止。

16chain_of_responsibility.png

抽象处理者角色 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

创建处理链,并向链头的具体处理者对象提交请求。

publict TestChainofResponsibility{
    
    public static void main(String[] args){
        Handler handler=new ConcreteHandlerA();
        Handler handlerB=new ConcreteHandlerB();
        handler.setNext(HandlerB);
        
        handler.handlerRequest("B");
    }
}

模式的扩展

  • 纯的职责链模式
  • 不纯的职责链模式:一个请求必须被某一个处理者对象接收。接收后两种处理一种自己处理或推给下家。
  • 允许出现某一个具体处理者对象在承担部分责任后,将其他责任传给下架的情况。
17state.png

五、状态模式 State

对有状态的对象,把复杂的判断逻辑提取到不同的状态对象中,允许状态对象在其内部状态改变是改变行为。

环境角色 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;
    }
}

抽象状态类 State

abstract State{
    void handle(Context context);
}

具体状态类 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");
        
    }
}

状态模式扩展

有些情况可能多个环境共享一组状态,这时候需要引入享元模式,状态放到集合中程序共享。

class ShareContext{
    private ShareState state;
    private HashMap 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);
    }
    
}

六、观察者模式

多个对象间存在一对多的依赖关系,当一个对象的状态发生改变是其它对象自动更新,这种模式有时候又称作发布-订阅模式。在软件开发中用的最多的是窗体程序设计中的事件处理,sping 中ApplicationContext 的事件机制也是通过该模式实现的。
优点: 降低了目标与观察者之间的耦合关系。目标与观察者之间建立了一套触发机制。
缺点:目标和观察者之间的医疗没有完全解除,可能导致循环引用。 当观察者对象很多时,通知观察者会花费很多时间,影响效率。


20observer.png

抽象主题 Subject

保存观察者对象的聚集类和增删方法,通知所有观察者。

abstract Subject{
    private  List 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();
    }
}

模式扩展

在java中,通过java.util.Observable类和 java.util.Observer 接口定义观察者模式。

1、Observable类
  • 抽象目标类,有一个Vector向量,用于保存需要通知的观察者对象
  • void addObserver(Observer o) 添加观察者
  • void notifyObservers(Object arg) 调用向量中观察者对象update方法
    ,越晚加入越先得到通知
  • void setChange() 用于设置内部标志位,为真时notifyObservers才会通知观察者。
2、Observer接口

抽象观察者,监视目标的变化。

具体目标观察者
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);
    }
}
调用类
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

定义一个中介对象来封装一系列对象之间的交互
优点:

  • 降低对象间耦合,使得对象可以独立复用
  • 对象间一对多的关系转变为一对一,提高系统灵活性
19mediator.png

抽象中介者 Mediator

定义了注册和转发的接口

abstract class Mediator{
    public abstract void register(Colleague colleagur);
    public abstract void relay(Colleague cl);
}

具体中介者 ConcreteMediator

class ConcreteMediator extands Mediator{
    private List 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("接收请求");
        
    }
    public void send(){
        System.out.println("发送请求");
        mediator.relay(this);
    }
}
class ConcreteColleague2 extends Colleague{
    public void receive(){
        System.out.println("接收请求");
        
    }
    public boid send(){
        System.out.println("发送请求");
        mediator.relay(this);
    }
}

八、迭代器 Iterator

提供一个对象来访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。聚合迭代非常密切,大多数语言在实现聚合类是都提供了迭代类。

  • 当需要为聚合对象提供多种遍历方式时。
  • 为遍历不同聚合结构提供统一的接口。
  • 访问聚合对象而无需暴露内部细节时。
20Iterator.png

抽象聚合 Aggregate

定义存储、添加、删除聚合对象以及创建迭代器对象接口。

interface Aggregate{
    public void add(Object o);
    public void remove(Object o);
    public Iterator getInterator();
}

具体迭代器 ConcreteAggregate

class ConcreteAggregate implements Aggregate{
    private List 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 list=null;
    private int index=-1;
    public ConcreteIterator(List list){
        this.list=list;
    }
    public boolean hasNext(){
        if(index 
 

模式的扩展

迭代器常常与组合模式结合起来使用,经常潜藏在组合模式的容器构成类中。

class Composite impelements Component{
    private List 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

将作用于某种数据结构中的各元素操作分离成独立的类,使得在不改变数据机构的前提下添加新的操作,为数据结构中的元素提供各种操作。数据元素和数据操作分离,是行为模式中最复杂的一种模式。


21visitor.png

抽象访问者 Visitor

为每个对应元素提供一个访问操作visit(),参数标识了被访问元素

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

对象结构 ObjectStruct

包含元素角色的容器,提供访问者访问元素

class ObjectStruct {
    private List elements=new ArrayList<>();
    public void accept(Visitor visitor){
        Iterator 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);
    }
}

客户端调用 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);
    }
}

模式扩展

访问这模式使用频率比较高的一种模式,通常与迭代器或组合模式联用。
以组合模式为例(主要具体元素类):

叶子构件 Leaf
class ConcreteLeafElement implements Element{
    void accept(Visitor v){
        v.visit(this);
    }
    void operatorLeaf(){
        System.out.print("leaf");
    }
}

树枝构件Composite

class CompositeElement implements Element{
    private List 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

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要的时能将该对象恢复到原先保存的状态。又叫快照模式。

22Memento.png

备忘录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
    }
}

发起人Originator

记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,可以访问备忘录里的所有信息。

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

模式扩展

和原型模式结合使用,可以拥有自备功能,省去了备忘录,主要变化在发起人。

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

给分析对象定义一个语言,并定义该语言的文法表示,在设计一个解释器来解释语言中的句子。该模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。

  • 优点: 扩展性好,可通过集成改变或扩展语法。 每个表达式都是类似的实现比较容易。
  • 缺点:解析器模式中通常使用大量的循环和递归调用,当解释的句子复杂时,运行速度很慢,且调试代码比较麻烦。

解释器模式通常用于对简单语言的编译或分析实例中,为了掌握好他的结构和实现,必须先了解编译原理中的“we文法、句子、语法树”等相关概念。

23interpret.png

抽象表达式 Abstract Expression

interface AbstractExpression{
    public Object interpret(String info);
}

终结符表达式 Terminal Expression

class TerminalExpressoin implements AbstractExpression{
private Set set=new HashSet();
    public boolean interpret(String info){
        if(set.contains(info)){
            return true;
        }
        return false;
    }
    public TerminalExpression(String[] data){
        for(int i=0;i

非终结符表达式 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]);
    }
}

环境 Context

class Context{
    private String[] citys={"韶关","广州"};
    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("免费");
        else System.out.println("扣费2元");
    }
}

客户端 TestInterpret

public class InterpreterPattern{
    public static void main(String[] args){
        Context bus=new Context();
        bus.freeRide("广东的妇女");
        bus.freeRide("韶关的年轻人");
    }
}

模式扩展

项目开发中,如果要对表达式进行分析计算,java提供了数学公式解析器: Expression4J、Jep等

你可能感兴趣的:(设计模式-行为型模式)