23种设计模式——行为型模型

责任链模式

将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象

责任链模式需要一个统一的抽象类

public abstract class Leader {
    protected String name;
    protected Leader nextLeader;   // 责任链上的后继对象

    public Leader(String name) {
        this.name = name;
    }
    // 设置责任链的后继对象
    public void setNextLeader(Leader nextLeader) {
        this.nextLeader = nextLeader;
    }

    /**
     * 处理请求的核心业务方法
     * @param lr
     */
    public abstract void handleRequest(LeaveRequest lr);
}

然后就是一系列链上的类

public class Director extends Leader {
    public Director(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest lr) {
        if (lr.getLeaveDays() < 3) {
            System.out.println(String.format("员工%s请假%s,理由是%s", lr.getEmpName(), lr.getLeaveDays(), lr.getReason()));
            System.out.println("主任" + this.name + "审批通过");
        } else {
            if (this.nextLeader != null) {
                this.nextLeader.handleRequest(lr);
            }
        }
    }
}

  

public class Manager extends Leader {
    public Manager(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest lr) {
        if (lr.getLeaveDays() < 10) {
            System.out.println(String.format("员工%s请假%s,理由是%s", lr.getEmpName(), lr.getLeaveDays(), lr.getReason()));
            System.out.println("经理" + this.name + "审批通过");
        } else {
            if (this.nextLeader != null) {
                this.nextLeader.handleRequest(lr);
            }
        }
    }
}

  

public class GeneralManager extends Leader {
    public GeneralManager(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest lr) {
        if (lr.getLeaveDays() < 30) {
            System.out.println(String.format("员工%s请假%s,理由是%s", lr.getEmpName(), lr.getLeaveDays(), lr.getReason()));
            System.out.println("总经理" + this.name + "审批通过");
        } else {
            System.out.println("莫非" + lr.getEmpName() + "想辞职,居然请假" + lr.getLeaveDays() + "天");
        }
    }
}

使用

public static void main(String[] args) {
    Leader l1 = new Director("张三");
    Leader l2 = new Manager("李四");
    Leader l3 = new GeneralManager("王五");
    // 组织责任链的关系
    l1.setNextLeader(l2);
    l2.setNextLeader(l3);

    // 开始请假操作
    LeaveRequest lr = new LeaveRequest("TOM", 10, "回老家探亲");
    l1.handleRequest(lr);
}

迭代器模式

提供一个可以遍历聚合对象的方式

迭代器包含两部分:

  • 聚合对象:负责存储数据

  • 迭代器:遍历数据

首先定义一个迭代器接口,里面定义一个迭代器需要的方法

public interface MyIterator {
    void first();  // 将游标指向第一个元素
    void next();  // 将游标指向下一个元素
    boolean hasNext();  // 是否有下一个元素
    boolean isFirst();
    boolean isLast();
    Object getCurrentObj();   // 获取当前游标指向的对象
}

然后定义聚合类跟迭代器类,迭代器类作为聚合类的内部类,天然可以使用聚合类的数据

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义聚合类
 */
public class ConcreateMyAggregate {
    private List<Object> list = new ArrayList<>();

    public void addObj(Object obj) {
        list.add(obj);
    }

    public void delObj(Object obj) {
        list.remove(obj);
    }

    public List<Object> getList() {
        return list;
    }

    public void setList(List<Object> list) {
        this.list = list;
    }

    /**
     * 获取迭代器
     * @return 返回内部迭代器
     */
    public MyIterator createIterator() {
        return new ConcreateIterator();
    }

    /**
     * 使用内部类定义迭代器,可以直接使用外部类的属性
     */
    private class ConcreateIterator implements MyIterator {
        private int cursor;   // 定义游标 用于记录遍历时的位置

        @Override
        public void first() {
            cursor = 0;
        }

        @Override
        public void next() {
            if (cursor < list.size()) {
                cursor++;
            }
        }

        @Override
        public boolean hasNext() {
            return cursor < list.size();
        }

        @Override
        public boolean isFirst() {
            return cursor == 0;
        }

        @Override
        public boolean isLast() {
            return cursor == list.size() - 1;
        }

        @Override
        public Object getCurrentObj() {
            return list.get(cursor);
        }
    }
}

使用

public static void main(String[] args) {
    ConcreateMyAggregate cma = new ConcreateMyAggregate();
    cma.addObj("aa");
    cma.addObj("bb");
    cma.addObj("cc");

    MyIterator mi = cma.createIterator();
    while (mi.hasNext()) {
        System.out.println(mi.getCurrentObj());
        mi.next();   // 游标向下移动一位
    }
}

中介者模式

解耦多个同事对象之间的交互关系。每个对象都持有中介者对象的引用,只跟中介者打交道。我们通过中介者同一管理这些交互关系

中介者对象

public interface Mediator {
    void register(String dname, Department d);

    void command(String dname);
}

  

public class President implements Mediator {
    private Map<String, Department> map = new HashMap<>();

    @Override
    public void register(String dname, Department d) {
        map.put(dname, d);
    }

    @Override
    public void command(String dname) {
        map.get(dname).selfAction();
    }
}

被解耦的对象

public interface Department {
    void selfAction();   // 做本部门的事情
    void outAction();    // 向总经理发出申请
}

  

public class Development implements Department {
    private Mediator m;   // 持有一个中介者的引用

    public Development(Mediator m) {
        this.m = m;
        // 将当前部门注册到中介者哪儿
        m.register("development", this);
    }

    @Override
    public void selfAction() {
        System.out.println("专心科研,开发项目");
    }

    @Override
    public void outAction() {
        System.out.println("汇报工作");

    }
}

  

public class Finacial implements Department {
    private Mediator m;   // 持有一个中介者的引用

    public Finacial(Mediator m) {
        this.m = m;
        // 将当前部门注册到中介者哪儿
        m.register("finacial", this);
    }

    @Override
    public void selfAction() {
        System.out.println("数钱");
    }

    @Override
    public void outAction() {
        System.out.println("汇报工作,钱太多了,怎么花");

    }
}

  

public class Market implements Department {
    private Mediator m;   // 持有一个中介者的引用

    public Market(Mediator m) {
        this.m = m;
        // 将当前部门注册到中介者哪儿
        m.register("market", this);
    }

    @Override
    public void selfAction() {
        System.out.println("跑去接项目");
    }

    @Override
    public void outAction() {
        System.out.println("汇报工作,项目承接的进度,需要资金支持");
        m.command("finacial");   // 中介对象调用财务部解决问题
    }
}

使用

public static void main(String[] args) {
    // 创建中介对象
    Mediator md = new President();

    Market m = new Market(md);
    Development d = new Development(md);
    Finacial f = new Finacial(md);

    m.selfAction();
    m.outAction();
}

命令模式

将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。也称之为动作模式或者事物模式

结构:

  • Command抽象命令类

  • ConcreateCommand具体命令类

  • Invoker调用者/请求者:发布命令的对象

  • Receiver接收者:真正执行命令的对象

  • Client客户类

解释器模式

  • 是一种不常用的模式

  • 用于描述如何构建一个简单的语言解释器,主要用于使用面向对象语言开发的编译器和解释器设计

  • 当我们需要开发一种新的语言时,可以考虑使用解释器模式

访问者模式

对于存储在一个集合中的对象,他们可能具有不同的类型,对于该集合中的对象,可以接受一类访问者对象来访问,不同的访问者访问方式也有所不同

策略模式strategy

策略模式对应于解决某一个问题的算法族,允许用户从该算法族中任选一个算法解决某一个问题,同时可以方便更换算法或者增加新的算法。并且由客户端决定调用哪个算法

策略模式需要一个上下文

负责配置具体的策略,调用策略的方法

/**
 * 负责和具体的策略类交互
 * 这样的话,算法就彻底和客户端调用分离了,使得算法可以独立于客户端变化
 * 如果使用spring的依赖注入功能,还可以通过配置文件动态的注入不同策略对象,动态的切换算法
 */
public class Context {
    private Strategy strategy;  // 当前采用的算法

    // 通过构造器来注入
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    // 可以通过set方法注入
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void printPrice(double s) {
        System.out.println("您该报价:" + strategy.getPrice(s));
    }
}

所有的策略类

public interface Strategy {
    double getPrice(double standardPrice);
}

  

public class NewCustomerFewStrategy implements Strategy {
    @Override
    public double getPrice(double standardPrice) {
        System.out.println("不打折,原价");
        return standardPrice;
    }
}

  

public class NewCustomerManyStrategy implements Strategy {
    @Override
    public double getPrice(double standardPrice) {
        System.out.println("打九折");
        return standardPrice * 0.9;
    }
}

  

public class OldCustomerFewStrategy implements Strategy {
    @Override
    public double getPrice(double standardPrice) {
        System.out.println("打八五折");
        return standardPrice * 0.85;
    }
}

  

public class OldCustomerManyStrategy implements Strategy {
    @Override
    public double getPrice(double standardPrice) {
        System.out.println("打八折");
        return standardPrice * 0.8;
    }
}

使用

public static void main(String[] args) {
    Strategy s = new OldCustomerFewStrategy();
    Context c = new Context(s);
    c.printPrice(998);
}

模板方法模式

模板方法模式是编程中经常用到的模式,它定义了一个操作中的算法骨架,将某些步骤延迟到子类中实现。这样,新的子类可以在不改变一个算法结构的前提下重新定义该算法的某些特定步骤

核心即处理步骤在父类中定义好,具体实现延迟到子类中定义

模板类

public abstract class BankTemplateMethod {
    // 具体方法
    public void takeNumber() {
        System.out.println("排队取票");
    }

    public abstract void transact();  // 办理具体的业务,这是一个钩子方法

    public void evaluate() {
        System.out.println("反馈评分");
    }

    public final void process() {
        this.takeNumber();
        this.transact();   // 该处是一个钩子,执行是勾着哪个子类就执行哪个方法
        this.evaluate();
    }
}

使用

public class Client {
    public static void main(String[] args) {
        BankTemplateMethod bm = new DrawMoney();
        bm.process();

        // 采用匿名内部类
        new BankTemplateMethod() {
            @Override
            public void transact() {
                System.out.println("我要存款");
            }
        }.process();
    }
}

class DrawMoney extends BankTemplateMethod {

    @Override
    public void transact() {
        System.out.println("我要取款");
    }
}

状态模式

用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题

结构:

  • Context环境类:环境类中维护了一个State对象,他是定义了当前的状态。

  • State抽象状态类

  • ConcreateState具体状态类:每一个类对应了一个状态对应的行为

context环境类

public class Context {
    private State state;

    public void setState(State state) {
        System.out.println("修改状态");
        this.state = state;
        state.handle();
    }
}

不同的状态类

public interface State {
    void handle();
}

  

/**
 * 空闲状态
 */
public class FreeState implements State {

    @Override
    public void handle() {
        System.out.println("房间空闲,没人入住");
    }
}

  

/**
 * 预定状态
 */
public class BookedState implements State {
    @Override
    public void handle() {
        System.out.println("房间已预定,别人不能定");
    }
}

  

/**
 * 已经预定
 */
public class CheckedInState implements State {
    @Override
    public void handle() {
        System.out.println("房间已入住,请勿打扰");
    }
}

使用

public static void main(String[] args) {
    Context ctx = new Context();

    ctx.setState(new FreeState());
    ctx.setState(new BookedState());
}

观察者模式

观察者模式主要用于一对多的通知,当一个对象的状态变化时,他需要及时告知一系列对象,令他们做出响应

通知观察者的方式:

  • 推:每次都会把通知以广播的方式发送给所有观察者,所有观察者只能被动接收

  • 拉:观察者只要知道有情况即可,至于什么时候获取内容,获取什么内容,都可以自主决定

目标对象

用户目标对象,用于通知所有的观察者

import java.util.LinkedList;
import java.util.List;

public class Subject {
    protected List<Observer> list = new LinkedList<>();

    public void register(Observer observer) {
        list.add(observer);
    }

    public void remove(Observer observer) {
        list.remove(observer);
    }

    // 通知所有观察者更新状态
    public void notifyAllObservers() {
        list.forEach(obj -> obj.update(this));
    }
}

  

public class ConcreateSubject extends Subject {
    private int state;

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        // 目标对象值发生了对象,请通知所有观察者
        this.notifyAllObservers();
    }
}

被观察对象

public interface Observer {
    void update(Subject subject);
}

  

public class ObserverA implements Observer {
    private int myState;  // myState需要跟目标对象的值保持一致

    @Override
    public void update(Subject subject) {
        // 主题对象中的状态发生变化后,会在这里对每个被观察对象进行改变
        myState = ((ConcreateSubject) subject).getState();
    }

    public int getMyState() {
        return myState;
    }

    public void setMyState(int myState) {
        this.myState = myState;
    }
}

使用

public static void main(String[] args) {
    // 创建目标对象
    ConcreateSubject cs = new ConcreateSubject();

    // 创建多个观察者
    ObserverA o1 = new ObserverA();
    ObserverA o2 = new ObserverA();
    ObserverA o3 = new ObserverA();
    ObserverA o4 = new ObserverA();

    // 让这4个观察者添加到subject对象的观察者队伍中
    cs.register(o1);
    cs.register(o2);
    cs.register(o3);
    cs.register(o4);

    // 现在改变subject的状态
    cs.setState(299);
    // 看看观察者的状态有没有变化
    System.out.println(o1.getMyState());
    System.out.println(o2.getMyState());
    System.out.println(o3.getMyState());
    System.out.println(o4.getMyState());
}

javaSE实现观察者模式

上面我们自己实现了观察者模式,其实在javaSE中已经定义了java.util.Observablejava.util.Observer,我们可以通过它们来实现观察者模式

目标对象

import java.util.Observable;

/**
 * 被观察者对象
 */
public class ConcreateSubject extends Observable {
    private int state;

    public void set(int s) {
        state = s;   // 目标对象状态发生了改变
        setChanged();   // 表明目标对象已经做了更改
        notifyObservers(state);  // 通知所有的观察者
    }

    public int getState() {
        return state;
    }
}

观察者对象

import java.util.Observable;
import java.util.Observer;

public class ObserverA implements Observer {
    private int myState;

    @Override
    public void update(Observable o, Object arg) {
        myState = ((ConcreateSubject) o).getState();
    }

    public int getMyState() {
        return myState;
    }

    public void setMyState(int myState) {
        this.myState = myState;
    }
}

使用

public static void main(String[] args) {
    // 创建目标对象
    ConcreateSubject c = new ConcreateSubject();

    // 创建观察者
    ObserverA o1 = new ObserverA();
    ObserverA o2 = new ObserverA();
    ObserverA o3 = new ObserverA();

    // 将上面的观察者对象添加到目标对象的观察者容器中
    c.addObserver(o1);
    c.addObserver(o2);
    c.addObserver(o3);

    // 改变subject对象的状态
    c.set(3000);

    // 查看观察者状态
    System.out.println(o1.getMyState());
    System.out.println(o2.getMyState());
    System.out.println(o3.getMyState());
}

备忘录模式 memento

场景:

  • 录入大批人员资料。正在录入当前人资料时,发现上一个人录错了,此时需要恢复上一个人的资料,再进行修改

  • 管理系统中,公文撤回功能。公文发送出去后,想撤回来

核心:就是保存某个对象内部状态的拷贝,这样以后就可以将该对象恢复到原先状态

结构:

  • 源发器类:Originator

  • 备忘录类:Memento

  • 负责人类:CareTake

源发类

/**
 * 源发器类
 */
public class Emp {
    private String ename;
    private int age;
    private double salary;

    // 进行备忘操作,并返回备忘录对象
    public EmpMemento memento() {
        return new EmpMemento(this);
    }

    // 进行数据恢复
    public void recovery(EmpMemento empMemento) {
        this.ename = empMemento.getEname();
        this.age = empMemento.getAge();
        this.salary = empMemento.getSalary();
    }

    public Emp(String ename, int age, double salary) {
        this.ename = ename;
        this.age = age;
        this.salary = salary;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

备忘录类

/**
 * 备忘录类
 */
public class EmpMemento {
    private String ename;
    private int age;
    private double salary;

    public EmpMemento (Emp emp) {
        this.ename = emp.getEname();
        this.age = emp.getAge();
        this.salary = emp.getSalary();
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

负责人类

/**
 * 负责人类
 * 管理备忘对象
 */
public class CareTake {
    private EmpMemento memento;  // 只能回复到上一个状态
//    private List<EmpMemento> list = new ArrayList<>();  // 多次备忘,可以恢复到前几个状态

    public EmpMemento getMemento() {
        return memento;
    }

    public void setMemento(EmpMemento memento) {
        this.memento = memento;
    }
}

使用

public static void main(String[] args) {
    CareTake take = new CareTake();

    Emp emp = new Emp("Sary", 18, 600);
    System.out.println(String.format("第一次打印对象%s,%s,%s", emp.getEname(), emp.getAge(), emp.getSalary()));

    take.setMemento(emp.memento());  // 备忘一次
    emp.setAge(49);
    emp.setEname("Lora");
    emp.setSalary(9000);
    System.out.println(String.format("第二次打印对象%s,%s,%s", emp.getEname(), emp.getAge(), emp.getSalary()));
    emp.recovery(take.getMemento());   // 恢复到备忘录保存的状态
    System.out.println(String.format("第三次打印对象%s,%s,%s", emp.getEname(), emp.getAge(), emp.getSalary()));
}

这就是所有的行为型结构

 

posted @ 2019-10-19 11:59  Jin同学  阅读(371)  评论(0编辑  收藏  举报