设计模式三-行为模式

策略设计模式

策略设计模式也叫算法族模式。目的是该算法改变的时候并不影响客户的使用。实现的基本思路非常简单,定义一个算法接口,然后各种不同的算法去实现这个接口,客户端调用使用的是接口而不是实现,说以当改变实现的时候客户端是不需要改变的。

/*
 * 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
 */
public interface ICalculator {
    public void calculate();
}
/**
 * 算法1
 */
public class Algorithm1 implements ICalculator{

    @Override
    public void calculate() {
    System.out.println("这是算法1");

    }

}
/*
 * 算法2
 */
public class Algorithm2 implements ICalculator {

    @Override
    public void calculate() {
        System.out.println("这是算法2");
    }

}
public class Client {
    public static void main(String[] args) {
    //当改变算法实现的时候改变这里创建的对象即可
        ICalculator calculator = new Algorithm1();
        calculator.calculate();
    }
}

模板设计模式

意图:定义实现一个逻辑的基本框架或者步骤,具体如何实现要由子类去完成。
原理:定义一个抽象类,抽象类中必须给出一个启动该逻辑的具体方法。逻辑的实现步骤由抽象方法定义。然后在具体方法中调用这些抽象方法。这样一个模板类就定义好了。要实现该模板类直接继承该模板类就OK了。

给出一个小例子:

/**
 * 模板类
 */
public abstract class Template {
    public void Calculate() {
        //这里不只是可以调用抽象方法,已经实现的方法或者是空方法都可调用
        method1();
        method2();
        method3();
        hookMethod();
    }

    /*
     * 逻辑实现的基本步骤交给子类去实现
     */
    public abstract void method1();

    public abstract void method2();

    public abstract void method3();
    /**
     * hook方法,可以在子类中override
     */
    public void hookMethod(){}
}
/**
 * 模板的实现类
 */
public class ConcreteTemplate extends Template {

    @Override
    public void method1() {
    System.out.println("method1");

    }

    @Override
    public void method2() {
        System.out.println("method2");

    }

    @Override
    public void method3() {
        System.out.println("method3");

    }
    @Override
    public void hookMethod(){
        System.out.println("hookmethod");
    }
}

public class Client {
    public static void main(String[] args) {
    Template template=new ConcreteTemplate();
    template.Calculate();

    }

}

输出:
method1
method2
method3
hookmethod

观察者模式

意图:观察者模式解决的问题是当一个对象发生改变的时候,要通知其他的对象发生了改变。
实现:被观察者对象内部维护一个队列,队列里边存放着观察者的引用。当被观察者状态发生改变的时候就会遍历队列里边的观察者并通知它们状态改变了。

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

/*
 * java为方便我们使用观察者模式,为我们提供了观察者的接口定义。
 */
public class Observer1 implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到状态更新的通知");

    }

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


public class Observer2 implements Observer{

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到状态更新的通知");

    }

}
import java.util.Observable;
/*
 * java为方便我们使用观察者模式,为我们提供了被观察者的接口定义。
 * 在这个抽象类中维护了一个集合和对这个集合进行操作的方法。有兴趣的可以看一下源码
 */
public class Subject extends Observable {
    // 更新状态,通知观察者
    public void Operation() {
        System.out.println("update State");
        setChanged();
        notifyObservers();
    }
}
import java.util.Observer;

public class Client {
    public static void main(String[] args) {
        //创建俩个观察者对象
        Observer observer1 = new Observer1();
        Observer observer2 = new Observer2();
        //创建被观察者
        Subject subject = new Subject();
        //添加观察者到被观察者中去
        subject.addObserver(observer1);
        subject.addObserver(observer2);
        //更新被观察者的状态
        subject.Operation();
    }

}

迭代器模式(Iterator)

目的:实现类似游标遍历集合中的内容一样的效果。
原理:直接看代码吧。

/**
 * 定义一个容器要实现的接口
 */
public interface Iteratorabel {
    public Iterator Iterator();
}
/*
 * 定义游标接口
 */
public interface Iterator {
      //前移  
    public Object previous();  

    //后移  
    public Object next();  
    public boolean hasNext();  

    //取得第一个元素  
    public Object first();  
}
/*
 * 定义一个容器应该有的基本方法
 */
public abstract class Collection implements Iteratorabel {

    @Override
    public Iterator Iterator() {
        // TODO Auto-generated method stub
        return null;
    }

    /*
     * 添加一个对象
     */
    public abstract void add(Object object);

    /*
     * 获取一个对象
     */
    public abstract void get(int i);

    /*
     * 删除一个对象
     */
    public abstract void remove(Object object);
}
/*
 * 实现一个容器实例
 */
public class MyCollection extends Collection {
    @Override
    public Iterator Iterator() {
        return new MyIterator(this);
    }

    @Override
    public void add(Object object) {
        System.out.println("add");
    }

    @Override
    public void get(int i) {
        System.out.println("get" + i);

    }

    @Override
    public void remove(Object object) {
        System.out.println("remove");

    }

}
/*
 * 实现一个游标
 */
public class MyIterator implements Iterator {
    Collection collection;

    public MyIterator(Collection collection) {
        this.collection = collection;
    }

    @Override
    public Object previous() {
        System.out.println("previous");
        return null;
    }

    @Override
    public Object next() {
        System.out.println("next");
        return null;
    }

    @Override
    public boolean hasNext() {
        System.out.println("has next");
        return false;
    }

    @Override
    public Object first() {
        System.out.println("first");
        return null;
    }
}
/*
 * 客户端
 */
public class Clietn {
    public static void main(String[] args) {
        //创建一个自定义集合
        Collection collection = new MyCollection();
        //返回它的迭代器
        Iterator iterator = collection.Iterator();
        //使用迭代器
        iterator.hasNext();
    }

}

责任链模式

目的:有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。
这里写图片描述
实现:Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象,MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。

/*
 * 定义处理任务需要实现的方法
 */
public interface IHandler {
    public void Operation();
}
/*
 * 定义形成责任链的基本框架
 */
public abstract class AbsHandler {
    //存储责任链上的下一个对象
    private IHandler handler;

    public IHandler getHandler() {
        return handler;
    }

    public void setHandler(IHandler handler) {
        this.handler = handler;
    }

}
/*
 * 责任链模式的实现类
 */
public class MyHandler extends AbsHandler implements IHandler {

    @Override
    public void Operation() {
        System.out.println("I am " + this);
        if (getHandler() != null) {
            getHandler().Operation();
        }
    }

}
/*
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        MyHandler h1 = new MyHandler();

        MyHandler h2 = new MyHandler();
        //设置责任链上的下一个处理对象
        h1.setHandler(h2);

        h1.Operation();
    }

}

命令设计模式

目的:实现命令的发送和执行者的解耦合
下面模拟一个使用遥控器控制电视打开关闭切换频道的功能:

/*
 * 定义一条命令
 */
public interface Command {
    public void excute();
}
/*
 * 切换频道的命令
 */
public class ChangeChanelCommand implements Command{
private TVReciver reciver;
public ChangeChanelCommand(TVReciver reciver){
    this.reciver=reciver;
}
    @Override
    public void excute() {
        reciver.changchanle();
    }

}
/*
 * 关闭电视的命令
 */
public class TurnoffCommand implements Command {
    private TVReciver reciver;

    public TurnoffCommand(TVReciver reciver) {
        this.reciver = reciver;
    }

    @Override
    public void excute() {
        reciver.turnoff();

    }

}
/*
 * 打开电视的命令
 */
public class TurnOnCommand implements Command {
    private TVReciver reciver;

    public TurnOnCommand(TVReciver reciver) {
        this.reciver = reciver;
    }

    @Override
    public void excute() {

        reciver.turnon();
    }

}
/*
 1. 命令接收着
 */
public class TVReciver {
    public void turnon() {
        System.out.println("打开电视");
    }

    public void changchanle() {
        System.out.println("切换频道");
    }

    public void turnoff() {
        System.out.println("关闭电视");
    }
}
/*
 2. 控制者,相当于invoker
 */
public class Controller {
    private Command onCommand, offCommand, changeChannel;

    public Controller(Command on, Command off, Command channel) {
        this.onCommand = on;
        this.offCommand = off;
        this.changeChannel = channel;
    }

    public void turnOn() {
        onCommand.excute();
    }

    public void turnOff() {
        offCommand.excute();
    }

    public void changeChannel() {
        changeChannel.excute();
    }
}
/*
 3. 客户端
 4. 命令模式的目的是实现命令的发送和执行者的解耦合。那么使用一个Command接口不就可以隔离命令的发送和实现么,为什么还要有一个接收者?
 5. 
 6. 关于这一点,是为了使这个模式更加的灵活同时也是符合现实的生活(面向对象嘛)。首先,作为一个命令的实际执行者,它不可能只会执行一条命
 7. 令,一般来说他会同时具备执行几个命令的能力。其次,当有一些复杂命令可以由其他的命令组合完成的时候,这个时候就可以复用接收者的这些个
 8. 能力了,代码更加灵活。

 */
public class Client {
    public static void main(String[] args) {
        // 命令的实际执行者
        TVReciver reciver = new TVReciver();
        // 创建命令
        Command commaTurnoffCommand = new TurnoffCommand(reciver);
        Command turnOnCommand = new TurnOnCommand(reciver);
        Command chanelCommand = new ChangeChanelCommand(reciver);
        // 命令发出者
        Controller controller = new Controller(turnOnCommand,
                commaTurnoffCommand, chanelCommand);
        // 发送命令
        controller.turnOn();
        controller.changeChannel();
        controller.turnOff();
    }
}

输出结果:

打开电视
切换频道
关闭电视

备忘录模式

目的:该模式的目的就是保存一个类的状态,在需要的时候恢复其状态。
原理:对于要恢复的类,我们需要对其必要的属性进行保存。然后在需要恢复其属性的时候根据已近保存的属性值进行赋值恢复其状态。

这里给出的例子,存储方式是存储在内存中,也可以选择其他的存储方式。

/*
 1. 需要保存状态的类
 */
public class Original {
    private String value;

    public Original(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    // 创建一个备份
    public Memento CreatMemento() {
        return new Memento(value);
    }

    // 还原状态
    public void Restorage(Memento memento) {
        this.value = memento.getValue();
    }
}
/*
 2. 备忘录类
 */
public class Memento {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public Memento(String value) {
        this.value = value;
    }
}
/*
 3. 保存备忘录类
 */
public class Storage {

  private Memento memento;  

  public Storage(Memento memento) {  
      this.memento = memento;  
  }  

  public Memento getMemento() {  
      return memento;  
  }  

  public void setMemento(Memento memento) {  
      this.memento = memento;  
  }
}
public class Client {
    public static void main(String[] args) {
        // 创建原始类
        Original origi = new Original("egg");

        // 创建备忘录
        Storage storage = new Storage(origi.CreatMemento());

        // 修改原始类的状态
        System.out.println("初始化状态为:" + origi.getValue());
        origi.setValue("niu");
        System.out.println("修改后的状态为:" + origi.getValue());

        // 回复原始类的状态
        origi.Restorage(storage.getMemento());
        System.out.println("恢复后的状态为:" + origi.getValue());
    }
}

输出结果:
初始化状态为:egg
修改后的状态为:niu
恢复后的状态为:egg

状态设计模式

状态设计模式

目的:当状态改变的时候,改变其行为。很好理解!就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态,所以,状态模式就两点:1、可以通过改变状态来获得不同的行为。2、你的好友能同时看到你的变化。

/*
 * 状态模式的核心类
 */
public class State {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public State(String value) {
        this.value = value;
    }
     public void method1(){  
            System.out.println("execute the first opt!");  
        }  

        public void method2(){  
            System.out.println("execute the second opt!");  
        }  
}
/*
 * 状态切换类
 */
public class Context {
    private State state;  

    public Context(State state) {  
        this.state = state;  
    }  

    public State getState() {  
        return state;  
    }  

    public void setState(State state) {  
        this.state = state;  
    }  

    public void method() {  
        if (state.getValue().equals("state1")) {  
            state.method1();  
        } else if (state.getValue().equals("state2")) {  
            state.method2();  
        }  
    }  
}
/*
 * 测试
 */
public class Test {

    public static void main(String[] args) {
           State state = new State("");  
            Context context = new Context(state);  

            //设置第一种状态  
            state.setValue("state1");  
            context.method();  

            //设置第二种状态  
            state.setValue("state2");  
            context.method();
    }

}

访问者设计模式

目的:访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
例子:

/*
 * 必须实现accept方法,以便实现Visitor和Node的双向引用。目的的达到在visitor中对调Node中访问数据的方法。
 */
public abstract class Node {
    /**
     * 接受操作
     */
    public abstract void accept(Visitor visitor);
}
/*
 * 通过传入的Node数据对象访问数据,实现对数据的操作。
 */
public interface Visitor {
    /**
     * 对应于NodeA的访问操作
     */
    public void visit(NodeA node);
    /**
     * 对应于NodeB的访问操作
     */
    public void visit(NodeB node);
}
public class VisitorA implements Visitor {
    /**
     * 对应于NodeA的访问操作
     */
    @Override
    public void visit(NodeA node) {
        System.out.println(node.operationA());
    }
    /**
     * 对应于NodeB的访问操作
     */
    @Override
    public void visit(NodeB node) {
        System.out.println(node.operationB());
    }
}
public class VisitorB implements Visitor {
    /**
     * 对应于NodeA的访问操作
     */
    @Override
    public void visit(NodeA node) {
        System.out.println(node.operationA());
    }
    /**
     * 对应于NodeB的访问操作
     */
    @Override
    public void visit(NodeB node) {
        System.out.println(node.operationB());
    }
}
public class NodeA extends Node{
    /**
     * 接受操作
     */
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    /**
     * NodeA特有的方法
     */
    public String operationA(){
        return "NodeA";
    }
}

public class NodeB extends Node{
    /**
     * 接受方法
     */
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    /**
     * NodeB特有的方法
     */
    public String operationB(){
        return "NodeB";
    }
}
import java.util.ArrayList;
import java.util.List;
/*
 * 存放数据访问Node
 */
public class ObjectStructure {

    private List<Node> nodes = new ArrayList<Node>();

    /**
     * 执行方法操作
     */
    public void action(Visitor visitor){

        for(Node node : nodes)
        {
            /*
             * 一:accept node中获得了visitor的引用
             * 二:node 反过来调用visitor的visit(Node node)方法 。此时node将自己的this传入。完成了Node和visitor之间的
             * 双重引用。在visitor方法中,传入的Node被调用,此时visitor就访问到了Node中的数据。接下来可以进行其他操作了。
             */
            node.accept(visitor);
        }

    }
    /**
     * 添加一个新元素
     */
    public void add(Node node){
        nodes.add(node);
    }
}
/*
 * 在数据结构不变的情况下,改变上层对数据的操作可以使用访问者设计模式。
 */
public class Client {

    public static void main(String[] args) {
          //创建一个结构对象
        ObjectStructure os = new ObjectStructure();
        //给结构增加一个节点
        os.add(new NodeA());
        //给结构增加一个节点
        os.add(new NodeB());
        //创建一个访问者
        Visitor visitor = new VisitorA();
        os.action(visitor);
    }
}

结果:
NodeA
NodeB

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章