设计模式 GOF23 行为型

设计模式 GOF23 提纲

设计模式 GOF23 创建型

设计模式 GOF23 结构型

设计模式 GOF23 行为型

行为型

行为型的模式,当然是拿行为做文章,比如:

  1. 把很多行为放在一个类内管理
  2. 抽象行为,使他可以被替换。
  3. 等等

责任链模式

场景:多个对象都有可能接受并处理请求,而客户端并不确定哪个对象能完成这个请求。
实现:每个对象设置下一个处理对象,如果自己不能处理,则传递下去。
常用实例:拦截器、过滤器、日志(级别)

public abstract class Dealer{
    
    
    private Dealer dealer;
    public void setNext(Dealder dealer){
    
     this.dealer = dealer; }
    public void getNext(){
    
     return dealer; }
    public abstract boolean deal(){
    
    }
}
public class ConcreteDealer extends Dealer{
    
    
    @Override
    public boolean deal(){
    
    
        if (getNext()!=null){
    
    
            System.out.println("go next");
            getNext().deal();
        }
        else{
    
    
            System.out.println("done");
        }
    }
}

public class Client{
    
    
    public static void main(String[] args){
    
    
        //可以看到链式的组成,对于这几个类是不可知的,他们只专注于处理和传递
        ConcreteDealer normalDealer = new ConcreteDealer();
        ConcreteDealer advancedDealer = new ConcreteDealer();
        ConcreteDealer expertDealer = new ConcreteDealer();
        normalDealer.setNext(advancedDealer);
        advancedDealer.setNext(expertDealer);
        normalDealer.deal();
    }
}

命令模式

场景:通常一个对象类包含多种请求,如果有多个类中的多个请求,要组合起来,方便调用。
实现:将请求包装成统一调用方法的命令类,并将对象组合到命令类内。
常用实例:Linux下命令
优缺点:
- 优点:用户体验极好,只需要关注命令类即可。
- 缺点:效率低下,滋生太多命令类

//简化命令类的统一调用函数。call execute都可以
public interface ICMD{
    
    public void call();}

public class OldOrder{
    
    
    private int orderId;
    public void setOrderId(int orderId){
    
     this.orderId = orderId; }
    public void getOrderId(int orderId){
    
     return orderId; }
    public void sell(){
    
     System.out.println("sell "+getOrderId());  };
    public void buy(){
    
     System.out.println("buy "+getOrderId());  };
}
public class CMDSell extends ICMD{
    
    
    private OldOrder oldOrder;
    public CMDSell(OldOrder oldOrder){
    
     this.oldOrder = oldOrder; }
    public void call(){
    
     this.oldOrder.sell(); }
}
public class CMDBuy extends ICMD{
    
    
    private OldOrder oldOrder;
    public CMDBuy(OldOrder oldOrder){
    
     this.oldOrder = oldOrder; }
    public void call(){
    
     this.oldOrder.buy(); }
}
public class TestDemo{
    
    
    public static void main(String[] args){
    
    
        OldOrder oldOrder = new OldOrder();
        oldOrder.setOrderId(999);
        new CMDBuy(oldOrder).call();
        new CMDSell(oldOrder).call();
    }
}

解释器模式

场景:一些固定的场景,比如表达式计算(ax^2 + bx+c),使用一个抽象语法树概括起来。
实现:使用终结符(计算单元)、非终结符(运算符号)、环境角色(对计算单元的赋值),通过抽象解释器,完成语法的解释。
常用实例:编译器、数学表达式计算(expression4J)、外挂脚本
优缺点:
- 优点:在生产、制作表达式时非常简单
- 缺点:类膨胀,如果需求一直变化,维护很麻烦
重点:终结符的interpreter得到值;而非终结符的interpreter得到更细的Expression。

//抽象解释器
public interface Expression{
    
    
    public Object interpreter(Context ctx);
}
//终结符/终结表达式/计算单元
public class TerminalExpression implements Expression{
    
    
    private String key;
    public TerminalExpression(String) key){
    
    
        this.key = key;
    }
    //环境,本例中,计算单元的运算结果,就是自己的key在ctx中对应的value
    public Object interpreter(Context ctx){
    
    
        return ctx[key];
    }
}
//非终结符/非终结表达式/计算符
// x^2 表达式
public class AddExpression implements Expression{
    
    
    //加法需要2个表达式;如果是开根号,就只需要一个了
    private Expression exp1;
    private Expression exp2;
    public SqartExpression(Expression exp1,Expression exp2){
    
    
        this.exp1 = exp1;
        this.exp2 = exp2;
    }
    //需要等两个exp的计算;两个exp可能是终结符,也可能是非终结符。
    public Object interpreter(Context ctx){
    
    
        return exp1.interpreter(ctx) + exp2.interpreter(ctx);
    }
}

迭代器模式

场景:提供一种方法,可以顺序访问聚合中的每一个对象,但是又不暴露聚合的其他细节。
实现:将这种访问的方法抽象出来,所有的聚合类继承他即可。
常用实例:JAVA 中的 iterator,其他语言也都有

public interface Iterator{
    
    
    public boolean hasNext();
    public Object Next();
}
public interface Container{
    
    
    public Iterator getIterator();
}
//具体容器类
public class ConcreteContainer implements Container{
    
    
    public String[] items = {
    
    "aaa","bbb","ccc"}
    public Iterator getIterator(){
    
    
        return new ConcreteIterator();
    }
    //内部具体枚举类
    private class ConcreteIterator implements Iterator{
    
    
        private int index;
        public boolean hasNext(){
    
    
            return index< names.length - 1;
        }
        public Object Next(){
    
    
            if (hasNext()){
    
    
                return items[++index];
            }
            else{
    
    
                return null;
            }
        }
    }
}
public class IteratorDemo {
    
    
    public static void main(String[] args) {
    
    
        ConcreteContainer concreteContainer = new ConcreteContainer();
        for(Iterator iter = concreteContainer.getIterator(); iter.hasNext();){
    
    
            String item = (String)iter.next();
            System.out.println("item = " + item);
        }  
    }
}

中介者模式

场景:多个对象之间存在关系,由于对象的数量较多,变得及其复杂,也很难维护、扩展。
实现:创建一个中介者,所有的通信行为,都通过这个中介。将网状通信改变为海星状通信。
常用实例:服务注册中心、网关、MVC(C是中介)
优缺点:
- 优点:解耦,一对多变成了一对一
- 缺点:中介者集成了太多关系,可能变得过于复杂。

//标准场景是聊天室
//一人对多人的聊天发送规则,变成了人和聊天室之间的发送规则
public class ChatRoom{
    
    
    public static void showMessage(User talker,String msg){
    
    
        //这里可以作规则,判断两者是好友?黑名单?陌生人?
        //这些规则统一在中介者作判断,而对象只负责发送和接收,这就是中介者的意义
        System.out.println(talker.getName()+":"+msg);
    }
}
public class User{
    
    
    private String name;
    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public User(String name){
    
    
        this.name  = name;
    }
    //这里仅仅演示一下中介模式的作用
    public void sendMessage(String message){
    
    
        ChatRoom.showMessage(this,message);
    }
}

备忘录模式

场景:在不破坏对象的前提下,将对象状态在外部保存起来,这样就可以恢复到保存的状态。
实现:
常用实例:ctrl+z、数据备份、游戏存档

//游戏,随着play,状态变化,可以存档,可以读档
public class Game{
    
    
    private String _state ="begin";
    public void play(String s){
    
     _state += s;}
    public Memeto save(){
    
    
        return new Memeto(this._state);
    }
    public void load(Memeto backup){
    
    
        this._state = backup.getState();
    }
}
//存档Memeto,当然还可以做个存档管理器,这里略了
public class Memeto{
    
    
    private String _state;
    public Memeto(String state){
    
     this._state=state;   }
    public String getState(){
    
    
        return this._state;
    }
}

观察者模式

场景:一对多,一个对象Subject变化时,通知到其他的关系对象(Observer)。
实现:在Subject中包含一组Observer,有变化时通知。
常用实例:Subscribe/Publish

public class Cat{
    
    
    private Vector mouses = new Vector();
    public void beObserverdBy(Mouse mouse){
    
    
        mouses.add(mouse);
    }
    public void roar(){
    
    
        for (Mouse mouse in mouses){
    
    
            mouse.runaway();
        }
    }
}
public class Mouse{
    
    
    private String name;
    public Mouse(String name){
    
     this.name = name }
    public void runaway(){
    
    
        System.out.println(name + ":猫来了,赶紧跑。。。");
    }
}
public class Client{
    
    
    public static void main(String[] args){
    
    
        Cat tom = new Cat();
        tom.beObserverdBy(new Mouse("Little Jerry"));
        tom.beObserverdBy(new Mouse("Big Jerry"));
        tom.roar();
    }
}

状态模式

场景:一个对象在不同状态下表现出不同的逻辑,这导致对象的每个逻辑都需要判断状态。可以理解为“如果有很多if else,考虑下状态模式”
实现:将对象的“状态”抽象出来,不同的状态包含一套处理对象的逻辑。当对象状态变化,整套逻辑跟随改变。
常用实例:订单状态(待付款、待收货、待评价)
比较:有点像命令模式,但是命令模式是命令内包含对象,状态模式是对象内包含模式。

public interface WorkState{
    
    
    //状态中的处理方法,都是以对象作为参数
    public void work(Context context);
    public void eat(Context context);
}
public class OnState implements WorkState{
    
    
    public void work(Context context){
    
    
        System.out.println("马上干活"+context.anyParams);
    }
    public void eat(Context context){
    
    
        System.out.println("忙呢,晚点吃"+context.anyParams);
    }
}
public class OffState implements WorkState{
    
    
    public void work(Context context){
    
    
        System.out.println("下班了,明天再说"+context.anyParams);
    }
    public void eat(Context context){
    
    
        System.out.println("吃吃吃"+context.anyParams);
    }
}
public class Context{
    
    
    private WorkState state=new OnState();
    private String anyParams;
    public void changeState(WorkState state){
    
    
        this.state=state;
    }
    public void change(String param){
    
    
        anyParams += param;
    }
    public void work(){
    
    
        state.work(this);
    }
    public void eat(){
    
    
        state.eat(this);
    }
}
public class Client{
    
    
    public static void main(String[] args){
    
    
        Context context = new Context();
        context.work();
        context.eat();
        context.change(" when state change");
        context.changeState(new OffState());
        context.work();
        context.eat();
    }
}

策略模式

场景:一个对象的行为希望在运行时能够动态改变。
实现:将这个行为抽象出来。通过给对象赋予不同的行为实例,达到动态改变行为。
常用实例:桌面开发的事件
优缺点:一个行为代码需要大量策略类去分别实现。
对比:
状态模式:抽象的是状态,将多个行为封装在一个状态类内;

public interface Strategy{
    
    
    public void Action();
}
public class FightStrategy extends Strategy{
    
    
    public void Action(){
    
    
        System.out.println("let's fight");
    }
}
public class RunStrategy extends Strategy{
    
    
    public void Action(){
    
    
        System.out.println("let's run");
    }
}
public class Context{
    
    
    public Strategy strategy;
    public void enemyComing(){
    
    
        strategy.action();
    }
}
public class Client{
    
    
    public static void main(String[] args){
    
    
        Context context = new Context();
        context.strategy = new FightStrategy();
        context.enemyComing();
        context.strategy = new RunStrategy();
        context.enemyComing();
    }
}

模板模式

场景:子类中有很多相同的内容。
实现:可以创建一个父类,包含这些相同的信息,同时把抽象的内容留给子类实现。
常用实例:常见的abstract父子类
对比:
策略模式:策略模式仅抽象了行为;模板模式抽象了整个类。

public abstract class Order{
    
    
    public abstract void send();
    public void create(){
    
    
        System.out.println("created by form");
        send();
    }
}
public class SeaOrder extends Order{
    
    
    public void send(){
    
    
        System.out.println("send by ship");
    }
}
public class AirOrder extends Order{
    
    
    public void send(){
    
    
        System.out.println("send by plane");
    }
}
public class Client{
    
    
    public static void main(String[] args){
    
    
        SeaOrder seaOrder = new SeaOrder();
        seaOrder.create();
        AirOrder airOrder = new AirOrder();
        airOrder.send();
    }
}

访问者模式

场景:对象自身结构变化不大,但是对结构中的Element有很多不同且不相关的操作。
实现:将这些Element的操作全部封装到访问者中,通过调用访问者,实现所有对象的操作。
常用实例:
优缺点:
- 优点:单一职责(所有对象的操作都封装到一个访问者)。
- 缺点:访问者根据具体类来区分调用哪个方法。

public abstract class Element{
    
    
    public abstract void accept(Visitor visitor);
}
public class House extends Element{
    
    
    private Element[] rooms;
    public House(){
    
    
        rooms = new Element[] {
    
    new BedRoom(),new BookRoom()};
    }
    public void accept(Visitor visitor){
    
    
        for (int i = 0; i < rooms.length; i++) {
    
    
            rooms[i].accept(visitor);
        }
        visitor.visit(this);
    }
}
public class BedRoom extends Element{
    
    
    public void accept(Visitor visitor){
    
    
        visitor.visit(this);
    }
}
public class BookRoom extends Element{
    
    
    public void accept(Visitor visitor){
    
    
        visitor.visit(this);
    }
}
public class Visitor{
    
    
    //所有内容在Visitor统一管理
    public void visit(House house){
    
    
        System.out.println("this is a big house");
    }
    public void visit(BedRoom bedRoom){
    
    
        System.out.println("this is a BedRoom");
    }
    public void visit(BookRoom bookRoom){
    
    
        System.out.println("this is a BookRoom");
    }
}
public class Client{
    
    
    public static void main(String[] args){
    
    
        Element house = new House();
        //主动邀请访问者
        house.accept(new Visitor());
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_36572983/article/details/102825105