JAVA 的23中设计模式之三:行为型模式

分类:

创建型模式(关注对象的创建过程):

               单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。

结构型模式(关注对象和类的组织):

               适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。

行为型模式(关注对象之间的交互,研究运行时对象之间的通信协作):

               模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、

               策略模式、职责链模式、访问者模式。

 

1,责任链模式(chain of responsibility):

概念:

         将能够处理同一类请求的对象连成一条链,请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,能则处理,不能则传递给链上的下一个对象。(简单来说就像斗地主,三个人算一条链,请求就是轮流出牌,其中一个不能出牌了,则跳到下一个人出牌。)

使用场景:

  •     java中,异常机制就是一种责任链模式。比如 try可以对应多个catch....
  •     Servlet开发中,过滤器的链式处理。

举例实现:

           (以请假条为例, 假如请假3天主任审批 , 大于3天小于10天经理审批,大于10天总经理审批)

1、
/**
 * 假条类
 */
public class LeaveRequest {
    private String empName;
    private int LeaveDays;
    private String reason;

    public LeaveRequest(String empName, int leaveDays, String reason) {
        this.empName = empName;
        LeaveDays = leaveDays;
        this.reason = reason;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public int getLeaveDays() {
        return LeaveDays;
    }

    public void setLeaveDays(int leaveDays) {
        LeaveDays = leaveDays;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

}

2、
/**
 * 抽象类
 */
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;
    }

    //处理请求的核心的业务方法
    public abstract  void handlerRequest(LeaveRequest request);
}

3、
public class Director extends Leader {
    public Director(String name) {
        super(name);
    }
    /**
     * 主任处理请求为3天以下的假期,超过三天交给主任的上级经理
     * @param request
     */
    public void handlerRequest(LeaveRequest request) {
        if (request.getLeaveDays() < 3){
                System.out.println("主任"+name+"处理了请求人:"+request.getEmpName()+"的假条,请求天数:"+request.getLeaveDays());
        }else{
            //假条超过3天,并且主任的上级不为null时,交给上级处理
            if (this.nextLeader != null){
                this.nextLeader.handlerRequest(request);
            }
        }
    }
}

4、
public class Manager extends Leader {

    public Manager(String name) {
        super(name);
    }

    /**
     * 经理处理请求为大于3天小于10天的假期,超过10天交给上级总经理处理
     * @param request
     */
    public void handlerRequest(LeaveRequest request) {
        if (request.getLeaveDays() < 10){
                System.out.println("经理:"+name+"处理了请求人:"+request.getEmpName()+"的假条,请求天数:"+request.getLeaveDays());
        }else{
            //假条超过10天,并且经理的上级不为null时,交给上级处理
            if (this.nextLeader != null){
                this.nextLeader.handlerRequest(request);
            }
        }
    }
}


5、
public class GeneralManager extends Leader {

    public GeneralManager(String name) {
        super(name);
    }

    /**
     * 总经理处超过10天的假条
     * @param request
     */
    public void handlerRequest(LeaveRequest request) {
        if (request.getLeaveDays() > 10){
                System.out.println("总经理:"+name+"处理了请求人:"+request.getEmpName()+"的假条,请求天数:"+request.getLeaveDays());
        }
    }
}

6、
// 测试方法

    public static void main(String[] args){
        //创建请假人
        LeaveRequest request = new LeaveRequest("小明",100,"");
        Leader l1 = new Director("小黑"); //创建主任
        Leader l2 = new Manager("小白");  //创建经理
        Leader l3 = new GeneralManager("老大"); //创建总经理

        //设置上下级关系
        l1.setNextLeader(l2);
        l2.setNextLeader(l3);
        //当改变请假天数时,审批人也会随之改变
        l1.handlerRequest(request);
    }

 

2,迭代器模式(iterator):

使用场景:

  •       聚合对象:存储数据。
  •       迭代器:遍历数据。

举例实现:

1、

public interface MyIterator {
    void first();  //将游标指向第一个元素
    void next();     //将游标指向下一个
    boolean hasNext();  //判断是否存在下一个元素

    boolean isFirst();
    boolean isLast();

    Object getCurrentObj(); //获取当前游标指向的对象
}

2、
/**
 * 自定义聚合类
 */
public class ConcreteMyAggregate {

    private List<Object> list = new ArrayList<Object>();



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

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

    public MyIterator createConcreteIterator(){
        return new ConcreteIterator();
    }

    //使用内部类定义迭代器,可以直接使用外部类的属性
    private class ConcreteIterator implements MyIterator {
        private int cursor; //默认从0开始

        public void first() {
            this.cursor = 0;
        }

        public boolean hasNext() {
            return list.size() > cursor;
        }

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

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

        public void next() {
            cursor++;
        }

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


3、
public class Client {

    public static void main(String[] args){
        ConcreteMyAggregate cc = new ConcreteMyAggregate();
        cc.addObj("111111111");
        cc.addObj("222222222");
        cc.addObj("333333333");
        cc.addObj("444444444");
        MyIterator concreteIterator = cc.createConcreteIterator();
        while (concreteIterator.hasNext()){
            System.out.println(concreteIterator.getCurrentObj());;
            concreteIterator.next();
        }
    }
}

 

3,中介者模式(Mediator):

 核心:

     当系统中的对象呈网状结构,对象之间存在多对多关系时,这些对象称为“同事对象”,我们可以引入一个“中介者对象”。使各个“同事对象”只跟中介者对象打交道,将同事对象直接沟通的网状形式,变为同事对象和中介者对象之间沟通的模式。

 角色:

  •     Mediator: 抽象中介者。定义了同事对象到中介者对象之间的接口。
  •     ConcreteMediator: 具体中介者。实现抽象中介者的方法,它需要知道所有的具体同事类,同时需要从具体的同事类那里接收信息,并且向具体的同事类发送信息。
  •     Colleague: 抽象同事类。
  •     ConcreteColleague: 具体同事类。每个具体同事类都只需要知道自己的行为即可,但是他们都需要认识中介者。
  • 在中介者模式中中介者对象处于核心地位,因为它定义了整个系统中所有具体同事类之间的关系。在整个系统中它主要承担两个方面的责任。

优缺点:

        优点:简化了对象之间的关系,将系统的各个对象之间的相互关系进行封装,将各个同事类解耦,减少了子类的生成。

        缺点:由于中介者对象封装了系统中对象之间的相互关系,导致其变得非常复杂,使得系统维护比较困难。

使用场景:

         MVC模式中,Controller 是中介者,根据 View 层的请求来操作 Model 层

 举例实现:

           ( 这里我们就以租房为例,这里中介机构充当租房者与房屋所有者之间的中介者。

1、

//抽象中介者
public abstract class Mediator {
    //申明一个联络方法
    public abstract void constact(String message,Person person);
}

2、
//抽象同事类
public abstract class Person {
    protected String name;
    protected Mediator mediator;
    
    Person(String name,Mediator mediator){
        this.name = name;
        this.mediator = mediator;
    }
    
}


3、
//两个具体同事类(ConcreteColleague)
public class HouseOwner extends Person{
 
    HouseOwner(String name, Mediator mediator) {
        super(name, mediator);
    }
    
    /**
     * @desc 与中介者联系
     * @param message
     * @return void
     */
    public void constact(String message){
        mediator.constact(message, this);
    }
 
    /**
     * @desc 获取信息
     * @param message
     * @return void
     */
    public void getMessage(String message){
        System.out.println("房主:" + name +",获得信息:" + message);
    }
}
public class Tenant extends Person{
    
    Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }
    
    /**
     * @desc 与中介者联系
     * @param message
     * @return void
     */
    public void constact(String message){
        mediator.constact(message, this);
    }
 
    /**
     * @desc 获取信息
     * @param message
     * @return void
     */
    public void getMessage(String message){
        System.out.println("租房者:" + name +",获得信息:" + message);
    }
}


4、
//具体中介者对象:中介结构、MediatorStructure:
public class MediatorStructure extends Mediator{
    //首先中介结构必须知道所有房主和租房者的信息
    private HouseOwner houseOwner;
    private Tenant tenant;
 
    public HouseOwner getHouseOwner() {
        return houseOwner;
    }
 
    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }
 
    public Tenant getTenant() {
        return tenant;
    }
 
    public void setTenant(Tenant tenant) {
        this.tenant = tenant;
    }
 
    public void constact(String message, Person person) {
        if(person == houseOwner){          //如果是房主,则租房者获得信息
            tenant.getMessage(message);
        }
        else{       //反正则是房主获得信息
            houseOwner.getMessage(message);
        }
    }
}

5、
//调用
public class Client {
    public static void main(String[] args) {
        //一个房主、一个租房者、一个中介机构
        MediatorStructure mediator = new MediatorStructure();
        
        //房主和租房者只需要知道中介机构即可
        HouseOwner houseOwner = new HouseOwner("张三", mediator);
        Tenant tenant = new Tenant("李四", mediator);
        
        //中介结构要知道房主和租房者
        mediator.setHouseOwner(houseOwner);
        mediator.setTenant(tenant);
        
        tenant.constact("听说你那里有三室的房主出租.....");
        houseOwner.constact("是的!请问你需要租吗?");
    }
}


 

4,命令模式(command):

概念:

        将一个请求封装为对象,从而使我们可用不通的请求对客户进行参数化。对请求派对或者记录请求日志,一级支持可撤销的操作。(也称为:动作Action模式,批量操作的 事务 Transaction模式)

角色:

  •     Command:抽象命令类
  •     ConcreteCommand:具体命令类。
  •     Invoker:调用者/请求者。它通过命令对象执行请求。
  •     Receiver:接受者执行与请求相关操作,具体实现对请求的业务处理。 

 使用场景:

         数据库的事务机制底层实现,批量执行操作。命令的撤销和恢复。

 举例实现:

1、
 interface Command {
    void execute();
}

class ConcreteCommand implements  Command{

     private Receiver receiver;
     private String commandMsg;

    public ConcreteCommand(String commandMsg , Receiver receiver) {
        this.commandMsg = commandMsg;
        this.receiver = receiver;
    }

    public void execute() {
        //命令的真正实现,
        System.out.println("请求者:"+commandMsg+"开始发起命令调用执行者的:receiver.action()");
        receiver.action();
    }
}


2、
public class Receiver {

    public void action(){
        System.out.println("执行者开始执行命令。。。");
    }

}


3、
public class Invoke {

    private List<Command> commandList = new ArrayList<Command>();

    //用于调用命令类的方法
    public void call(){
        for (Command command : commandList) {
            command.execute();
            System.out.println();
        }
    }

    public static void main(String[] args){
       Command command1 = new ConcreteCommand("小明",new Receiver());
       Command command2 = new ConcreteCommand("小白",new Receiver());
       Command command3 = new ConcreteCommand("小黑",new Receiver());
       Command command4 = new ConcreteCommand("小绿",new Receiver());
       Invoke invoke = new Invoke();
       invoke.commandList.add(command1);
       invoke.commandList.add(command2);
       invoke.commandList.add(command3);
       invoke.commandList.add(command4);
       //执行发起者命令:
        invoke.call();
    }
}

 

5,命令模式(command):

概念:

        不常用的设计模式,用于使用面向对象语言开发的编译器和解释器设计。

使用场景:

        EL表达式、正则表达式、SQL语法解释器、数学表达式(如:Math Expression  String Parser)之类...

6,访问者模式(Visitor):

概念:

         对于存储在一个集合中的对象,他们可能具有不同类型,针对集合中不同类型的对象进行处理时,可以接受一类成为访问者对象,不同访问者其访问方式也不同。

使用场景:

        XML文档解析器设计、编译器设计、复杂集合对象处理。

7,策略模式(strategy):

概念:

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

 

 举例实现:

未使用策略模式的业务代码:

使用策略模式,将业务拆分成多个子类,方便业务扩展,然后由客户端调用来获取对应的结果:

package com.panger.strategy;

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

class NewCustomerFewStrategy implements Strategy {
    public double getPrice(double standardPrice) {
        System.out.println("新单个用户,不打折,原价");
        return standardPrice;
    }
}

class NewCustomerManyStrategy implements Strategy {
    public double getPrice(double standardPrice) {
        System.out.println("新批量用户,打九折");
        standardPrice = standardPrice * 0.9;
        return standardPrice;
    }
}

class OldCustomerFewStrategy implements Strategy {
    public double getPrice(double standardPrice) {
        System.out.println("老用户,打八五折");
        standardPrice = standardPrice * 0.85;
        return standardPrice;
    }
}

class OldCustomerManyStrategy implements Strategy {
    public double getPrice(double standardPrice) {
        System.out.println("批量老用户,打八折");
        standardPrice = standardPrice * 0.8;
        return standardPrice;
    }
}

/**
 * 负责和具体策略类交互
 * 具体的算法和直接客户调用分离了,使得算法可以独立于客户端独立变化。
 */
class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void printPrice(double d) {
        System.out.println( strategy.getPrice(d));
    }


    //调用
    public static void main(String[] args) {
        Context ctx1 = new Context(new NewCustomerFewStrategy());
        ctx1.printPrice(1000);

        Context ctx2 = new Context(new NewCustomerManyStrategy());
        ctx2.printPrice(1000);

        Context ctx3 = new Context(new OldCustomerManyStrategy());
        ctx3.printPrice(1000);
    }
}

 

 

 8,模板方法模式(template method):

概念:

         定义一个操作中的算法骨架,将某些步骤延迟到子类中实现。这样,新的子类可以在不改变一个算法结构的前提下重新定义该算法的某些特定步骤。核心:类的多态性

常用场景:

  •     数据库访问的封装。
  •     Spring中JDBC Template之类...

举例实现:

public abstract class  BankTemplateMethod {
    public void takeNumber(){
        System.out.println("取号排队");
    }
    public void evaluate(){
        System.out.println("反馈评分");
    }
    public abstract void transact(); //钩子方法:办理具体业务

    //模板方法
    public final void process(){
        this.takeNumber();
        this.transact();
    }

    public static void main(String[] args){
        //采用匿名内部类实现模板方法调用
        BankTemplateMethod btm = new BankTemplateMethod() {
            @Override
            public void transact() {
                System.out.println("我要取款!");
            }
        };
        btm.process();
        System.out.println();
        //采用匿名内部类实现模板方法调用
        BankTemplateMethod btmbtm = new BankTemplateMethod() {
            @Override
            public void transact() {
                System.out.println("我要该业务!");
            }
        };
        btmbtm.process();
    }
}

 

 9,状态模式(state):

概念:

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

角色:

  •   Context环境类:维护一个state对象,他是定义了当前状态。
  •   State抽象状态类:
  •   ConcreteState具体状态类:每一个类封装了一个状态对应的行为。

举例实现:

public interface State {
    void  handle();
}
//ConcreteState 具体类
class FreeState implements  State{
    public void handle() {
        System.out.println("房间空闲,无人住");
    }
}
//ConcreteState 具体类
class ReservationState implements  State{
    public void handle() {
        System.out.println("预定状态,无人住");
    }
}
//ConcreteState 具体类
class CheckedInState implements  State{
    public void handle() {
        System.out.println("房间已入住");
    }
}

//房间对象
class Context{
    private State state;
    public void setState(State state) {
        System.out.println("房间持有状态:");
        this.state = state;
        state.handle();
    }

    public static void main(String[] args){
        Context ctx =new Context();
        ctx.setState(new FreeState());
        System.out.println();
        ctx.setState(new ReservationState());
    }
}

 

10,观察者模式(Observer):

 概念:

         当一个对象(目标对象:Subject货Objserver)的状态变化时,他需要及时告知旗下的一系列对象(观察者对象,订阅者对象),令他们做出响应。(比如:多个用户在群里聊天便是用的观察者模式)

通知观察者的方式:

  •    推: 由目标对象主动推送给观察者,所有观察者只能被动接收。
  •    拉: 观察者去主动联系目标对象查看状态是否有变化。

 举例实现(以 "推" 的方式):

1,手动:

public interface Observer {
    void update(Subject subject);

}

class Subject {
    //观察者队伍
    private List<Observer> list = new ArrayList<Observer>();

    public void register(Observer observer) {
        list.add(observer);
    }
    public void remove(Observer observer) {
        list.remove(observer);
    }
    public void updateAllObserver() {
        for (Observer observer : list) {
            observer.update(this);
        }
    }
}

//目标对象
class ConcreteSubject extends Subject {
    private int state;
    public int getState() {
        return state;
    }
    //当目标对象的状态发生变化,便通知旗下所有观察者
    public void setState(int state) {
        this.state = state;
        super.updateAllObserver();
    }
}

//观察者
class ObserverA implements Observer {

    //与目标对象的 state 值一致
    private int myState;

    public void update(Subject subject) {
        myState = ((ConcreteSubject)subject).getState();
    }
    public int getMyState() {
        return myState;
    }
    public void setMyState(int myState) {
        this.myState = myState;
    }
}
class Client{

    public static void main(String[] args){
        ObserverA a1 = new ObserverA();
        ObserverA a2 = new ObserverA();
        ObserverA a3 = new ObserverA();

        ConcreteSubject sub  = new ConcreteSubject();
        sub.register(a1);
        sub.register(a2);
        sub.register(a3);
        sub.setState(3000);

        System.out.println(a1.getMyState());
        System.out.println(a2.getMyState());
        System.out.println(a3.getMyState());
        System.out.println();
    }
}

2,jdk自带生成观察者(java.util.Observable  java.util.Observer):

//目标对象
class ConcreteSubject extends Observable {
    private int state;
    public int getState() {
        return state;
    }
    public void setState(int state){
        this.state = state;
        setChanged();//表示目标对象已经做出更改
        notifyObservers(state); //通知旗下所有观察者
    }
}

//观察者
class ObserverA implements  Observer{
    //与目标对象的 state 值一致
    private int myState;
    public int getMyState() {
        return myState;
    }
    public void update(Observable o, Object arg) {
        myState = ((ConcreteSubject)o).getState();
    }
}
class Client{
    public static void main(String[] args){
        ObserverA a1 = new ObserverA();
        ObserverA a2 = new ObserverA();
        ObserverA a3 = new ObserverA();

        ConcreteSubject sub  = new ConcreteSubject();
        sub.addObserver(a1);
        sub.addObserver(a2);
        sub.addObserver(a3);
        sub.setState(3000);

        System.out.println(a1.getMyState());
        System.out.println(a2.getMyState());
        System.out.println(a3.getMyState());
        System.out.println();
    }
}

 

11,备忘录模式(memento):

概念:

        保存某个对象内部状态的拷贝,方便以后将该对象恢复到原先的状态。

常见场景:

        数据库软件中,事务的回滚模式。

角色:

  •    源发器类(Originator):
  •    备忘录类(Memento):
  •     负责人类(CareTaker):

 

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

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    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 EmpMemento memento(){
        return new EmpMemento(this);
    }
    //恢复操作
    public void recovery(EmpMemento mmt){
        this.name = mmt.getName();
        this.age = mmt.getAge();
        this.salary = mmt.getSalary();
    }

}

//备忘录类
class EmpMemento{
    private String name;
    private int age;
    private double salary;

    public EmpMemento(Emp emp){
        this.age = emp.getAge();
        this.name = emp.getName();
        this.salary = emp.getSalary();
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public double getSalary() {
        return salary;
    }
}

//负责人类
class CareTaker{
    private EmpMemento memento;

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


    public static void main(String[] args){
        CareTaker taker = new CareTaker();
        Emp emp = new Emp("小明" , 18,900);
        System.out.println("第一次:emp.getName()"+emp.getName()+"+emp.getAge()"+emp.getAge()+"+emp.getSalary() = "+emp.getSalary());
        taker.setMemento(emp.memento()); //备份一次

        System.out.println("###对原对象数据进行修改####");
        emp.setAge(38);
        emp.setName("小白");
        emp.setSalary(10000);
        System.out.println("第二次:emp.getName()"+emp.getName()+"+emp.getAge()"+emp.getAge()+"+emp.getSalary() = "+emp.getSalary());
        System.out.println("###对原对象恢复####");
        emp.recovery(taker.memento);
        System.out.println("第三次:emp.getName()"+emp.getName()+"+emp.getAge()"+emp.getAge()+"+emp.getSalary() = "+emp.getSalary());
        System.out.println();
    }
}

备忘点较多时:

 

 

 

完结。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值