设计模式之行为型模式
行为型模式总共分为11种:策略模式(strategy pattern)、模版方法模式(Template pattern)、观察者模式(observer pattern)、迭代器模式(iterator pattern)、责任链模式(Chain of responsibility pattern)、命令模式(Command pattern)
备忘录模式(Memento pattern)、状态模式(State pattern)、访问者模式(visitor pattern)、中介者模式(Mediator pattern)、解释器模式(Interpreter pattern)
一、策略模式(strategy pattern)
策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会 影响到环境和客户端。
public interface Strategy { public int doOperation(int num1, int num2); } public class AddStrategy implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 + num2; } } public class MinusStrategy implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 - num2; } } public class StrategyTest { public static void main(String[] args) { Strategy addStrategy = new AddStrategy(); int result1 = addStrategy.doOperation(1, 2); System.out.println(result1); Strategy minusStrategy = new MinusStrategy(); int result2 = minusStrategy.doOperation(1, 2); System.out.println(result2); } }
二、模版方法模式(Template pattern)
模板方法模式预备一个抽象类,在该抽象类的方法中只实现部分逻辑,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同 的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类来实现。
public abstract class AbstractCalculator { public int calculate(String exp, String opt) { split(exp, opt); int array[] = split(exp, opt); return calculate(array[0], array[1]); } private int[] split(String exp, String opt) { String array[] = exp.split(opt); int arrayInt[] = new int[2]; arrayInt[0] = Integer.parseInt(array[0]); arrayInt[1] = Integer.parseInt(array[1]); return arrayInt; } protected abstract int calculate(int num1, int num2); } public class AddCalculator extends AbstractCalculator { @Override protected int calculate(int num1, int num2) { return num1 + num2; } } public class TemplateTest { public static void main(String[] args) { String exp = "1+2"; AbstractCalculator cal = new AddCalculator(); int result = cal.calculate(exp, "\\+"); System.out.println(result); } }
三、观察者模式(observer pattern)
让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
public class Subject { private List<Observer> observerList = new ArrayList<>(); private int state; public void setState(int state) { this.state = state; notifyAllObservers(); } public int getState() { return state; } public void attach(Observer observer){ observerList.add(observer); } private void notifyAllObservers() { for (Observer obs : observerList) { obs.update(); } } }
public abstract class Observer { public abstract void update(); } public class SubObserver1 extends Observer { public SubObserver1(Subject subject){ subject.attach(this); } @Override public void update() { System.out.println("SubObserver1 update..."); } } public class SubObserver2 extends Observer { public SubObserver2(Subject subject){ subject.attach(this); } @Override public void update() { System.out.println("SubObserver2 update..."); } }
public class ObserverTest { public static void main(String[] args) { Subject sub = new Subject(); new SubObserver1(sub); new SubObserver2(sub); sub.setState(1); sub.setState(2); } }
四、迭代器模式(iterator pattern)
迭代器模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。 迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代器模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭 代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。这个模式在java集合类中非常常见
public interface MyCollection<E> { MyIterator<E> iterator(); //添加元素 boolean add(E e); //删除该元素 boolean remove(E e); /*取得集合大小*/ public int size(); //是否为空 boolean isEmpty(); } public interface MyIterator<E> { boolean hasNext(); E next(); void remove(); } public class MyList<E> implements MyCollection<E>{ private static final Object[] EMPTY_ELEMENTDATA = {}; private static final int DEFAULT_CAPACITY = 10; private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private Object[] elementData; private int size; private int modCount = 0; public MyList(){ this.elementData = EMPTY_ELEMENTDATA; } @Override public MyIterator<E> iterator() { return (MyIterator<E>) new MyIter(); } @SuppressWarnings("unchecked") public E get(int index) { if (index >= size) throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); return (E) elementData[index]; } @Override public boolean add(E e) { int minCapacity = size + 1; if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } modCount++ ; if (minCapacity - elementData.length > 0) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0){ newCapacity = minCapacity; } if (newCapacity - MAX_ARRAY_SIZE > 0){ if (minCapacity < 0){ throw new OutOfMemoryError(); } newCapacity = (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE : MAX_ARRAY_SIZE; } elementData = Arrays.copyOf(elementData, newCapacity); } elementData[size++] = e; return true; } @Override public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++){ if (elementData[index] == null) { fastRemove(index); System.out.println(elementData.length); return true; } } } else { for (int index = 0; index < size; index++){ if (o.equals(elementData[index])) { fastRemove(index); return true; } } } return false; } @SuppressWarnings("unchecked") public E remove(int index) { if (index >= size){ throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); } modCount++; E oldValue = (E)elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; return oldValue; } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0){ System.arraycopy(elementData, index+1, elementData, index,numMoved); } elementData[--size] = null; } @Override public int size() { return size; } @Override public boolean isEmpty() { return size == 0; } public String toString() { MyIterator<E> it = iterator(); if (!it.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (!it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } } private class MyIter implements MyIterator<E>{ int cursor; int lastRet = -1; int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size){ throw new NoSuchElementException(); } Object[] elementData = MyList.this.elementData; if (i >= elementData.length){ throw new ConcurrentModificationException(); } cursor = i + 1; return (E) elementData[lastRet = i]; } public void remove() { if (lastRet < 0){ throw new IllegalStateException(); } checkForComodification(); try { MyList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } } public class IteratorTest { public static void main(String[] args) { MyCollection<String> collection = new MyList<>(); System.out.println(collection.size()); collection.add("a"); collection.add("b"); collection.add("c"); MyIterator<String> iterator = collection.iterator(); while(iterator.hasNext()){ iterator.next(); System.out.println(collection); iterator.remove(); } } }
五、责任链模式(Chain of responsibility pattern)
在 责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪 一个对象终极处理这个请求,系统可以在不影响客户的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以终 极不被任何接收端对象所接受。
public interface Handler { void doOperate(); } public abstract class AbstractHandler implements Handler { private Handler nextHandler; public void setNextHandler(Handler nextHandler){ this.nextHandler = nextHandler; } public Handler getNextHandler(){ return nextHandler; } } public class Handler1 extends AbstractHandler { @Override public void doOperate() { System.out.println("handler1 处理。。。"); Handler nextHandler = getNextHandler(); if(nextHandler != null){ nextHandler.doOperate(); } } } public class Handler2 extends AbstractHandler { @Override public void doOperate() { System.out.println("handler2 处理。。。"); Handler nextHandler = getNextHandler(); if(nextHandler != null){ nextHandler.doOperate(); } } } public class ChainOfResposibilityPatternTest { public static void main(String[] args) { Handler1 handler1 = new Handler1(); Handler2 handler2 = new Handler2(); handler1.setNextHandler(handler2); handler1.doOperate(); } }
六、命令模式(Command pattern)
命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。 命令模式答应请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接 口,更不必知道请求是怎么被接收,以及操纵是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。
public interface Command { void execute(); } public class MyCommand implements Command { private Reciver reciver; public MyCommand(Reciver reciver){ this.reciver = reciver; } @Override public void execute() { reciver.action(); } } public class Reciver { public void action() { System.out.println("reciver action..."); } } public class Invoker { private Command command; public Invoker(Command command) { this.command = command; } public void invoke(){ command.execute(); } } public class CommandTest { public static void main(String[] args) { Reciver reciver = new Reciver(); Command command = new MyCommand(reciver); Invoker invoker = new Invoker(command); invoker.invoke(); } }
七、备忘录模式(Memento pattern)
保存一个对象的某个状态,以便在适当的时候恢复对象。
public class Original { private String state; public String getState() { return state; } public void setState(String state) { this.state = state; } public Memento saveState(){ return new Memento(state); } public void restoreState(Memento memento){ this.state = memento.getState(); } } public class Memento { private String state; public Memento(String state) { this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; } } public class Storage { private List<Memento> mementos = new ArrayList<>(); public Memento getMemento(int index) { return mementos.get(index); } public void setMemento(Memento memento) { mementos.add(memento); } } public class MementoTest { public static void main(String[] args) { Storage storage = new Storage(); Original o = new Original(); o.setState("a"); storage.setMemento(o.saveState()); System.out.println(o.getState()); o.setState("b"); storage.setMemento(o.saveState()); System.out.println(o.getState()); o.setState("c"); storage.setMemento(o.saveState()); System.out.println(o.getState()); o.setState("d"); storage.setMemento(o.saveState()); System.out.println(o.getState()); System.out.println("-------------------"); //开始恢复 o.restoreState(storage.getMemento(0)); System.out.println(o.getState()); o.restoreState(storage.getMemento(1)); System.out.println(o.getState()); o.restoreState(storage.getMemento(2)); System.out.println(o.getState()); o.restoreState(storage.getMemento(3)); System.out.println(o.getState()); } }
八、状态模式(State pattern)
状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便 改变所选的子类。
public abstract class State { private String state; public String getState() { return state; } public void setState(String state) { this.state = state; } public abstract void doOperation(); } public class RunningState extends State { @Override public void doOperation() { System.out.println("running..."); } } public class StoppingState extends State { @Override public void doOperation() { System.out.println("stopping..."); } }
public class Context { private State state; public State getState() { return state; } public void setState(State state) { this.state = state; } public void method(){ state.doOperation(); } } public class StateTest { public static void main(String[] args) { Context context = new Context(); context.setState(new RunningState()); context.method(); context.setState(new StoppingState()); context.method(); } }
九、访问者模式(visitor pattern)
访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操纵需要修改的话,接受这个操作的数据结构可以保持 不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增 加新的操作变的很轻易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时, 要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
public interface Visitor { public void visit(Subject sub); } public class MyVisitor implements Visitor { @Override public void visit(Subject sub) { System.out.println("visit the subject"); } } public interface Subject { public void accept(Visitor visitor); } public class MySubject implements Subject { @Override public void accept(Visitor visitor) { visitor.visit(this); } } public class VisitorTest { public static void main(String[] args) { Visitor visitor = new MyVisitor(); Subject sub = new MySubject(); sub.accept(visitor); } }
十、中介者模式(Mediator pattern)
用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。
public interface User { void work(); } public class User1 implements User { @Override public void work() { System.out.println("user1 work..."); } } public class User2 implements User { @Override public void work() { System.out.println("user2 work..."); } }
public class Mediator { private User user1; private User user2; public User getUser1() { return user1; } public void setUser1(User user1) { this.user1 = user1; } public User getUser2() { return user2; } public void setUser2(User user2) { this.user2 = user2; } public void doOperation(){ user1.work(); user2.work(); } } public class MediatorTest { public static void main(String[] args) { Mediator mediator = new Mediator(); mediator.setUser1(new User1()); mediator.setUser2(new User2()); mediator.doOperation(); } }
十一、解释器模式(Interpreter pattern)
定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。
解释器 模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。
在解释器模式中需 要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。
命令对象的等级结构中的对象的 任何排列组合都是一个语言。