一、策略模式
定义:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到算法的客户。
使用场景:策略模式是一种定义一系列算法的方法,从概念上看,所有的这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。策略模式的strategy类层次定义了一系类的可供重用的算法或行为。继承有助于析取出这些算法的中的公共功能。策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口进行单独测试。
示意图:
实例:
算法类接口和实现类:
package com.softline.strategy;
public interface IStrategy {
public void strateMethod();
}
package com.softline.strategy;
public class StrategyA implements IStrategy {
@Override
public void strateMethod() {
// TODO Auto-generated method stub
System.out.println("This is strategyA!");
}
}
package com.softline.strategy;
public class StrategyB implements IStrategy {
@Override
public void strateMethod() {
// TODO Auto-generated method stub
System.out.println("this is strategyB!");
}
}
上下文实现类:
package com.softline.strategy;
public class Context {
private IStrategy strategy;
public Context(IStrategy strategy){
this.strategy=strategy;
}
public void strategyMethod(){
strategy.strateMethod();
}
}
客户端:
package com.softline.strategy;
public class Client {
public static void main(String[] args) {
Context context = new Context(new StrategyA());
context.strategyMethod();
}
}
windows:
This is strategyA!
二、模板方法模式
定义:定义了一个类中算法的骨架,而将一些步骤延迟到y子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
使用场景:模板模式是通过把不变的行为搬到超类,去除子类中重复代码来体现它的优势。当不变和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板方法模式把这些行为搬到单一的地方,这样就帮助子类摆脱重复的不变的行为的纠缠。
示意图:
实例:
模板抽象类以及对应实现类:
package com.softline.TemplateMethod;
public abstract class ICookTemplate {
public final void cook(){
this.pourOil();
this.heatOil();
this.pourVegetable();
this.pourSauce();
this.fly();
}
public void pourOil(){
System.out.println("倒油...");
}
public void heatOil(){
System.out.println("热油...");
}
public void pourVegetable(){
System.out.println("到蔬菜...");
}
public void pourSauce(){
System.out.println("到调料...");
}
public void fly(){
System.out.println("翻炒...");
}
}
package com.softline.TemplateMethod;
public class Qingcai extends ICookTemplate {
@Override
public void pourVegetable(){
System.out.println("倒青菜...");
}
@Override
public void pourSauce(){
System.out.println("倒盐...");
}
}
package com.softline.TemplateMethod;
public class Carrot extends ICookTemplate {
public void pourVegetable(){
System.out.println("倒胡萝卜...");
}
public void pourSauce(){
System.out.println("倒胡椒粉...");
}
}
测试客户端
package com.softline.TemplateMethod;
public class Client {
public static void main(String[] args) {
Qingcai qingcai = new Qingcai();
Carrot carrot = new Carrot();
qingcai.cook();
System.out.println("-----------------------");
carrot.cook();
}
}
三、观察者模式
定义:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象使他们能够自动更新自己。
使用场景:将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象之间的一致性。我们不希望为了维护一致性而使各类之间紧密耦合,这样会给维护、扩展、重用带来不便。当一个对象的改变需要改变其他对象时,而且他并不知道需要改变多少对象时需要使用观察者模式。一个抽象模型有两个方面,其中一方面依赖于另一个方面,这时使用观察者模式可以将这两者封装在独立的对象当中使他们各自独立的改变和复用。观察者模式所做的工作就是解除耦合,让耦合双方都依赖于抽象,而不是依赖于具体。从而使各自的变化都不会影响另一边的变化。
示意图:
实例:
观察者实现接口、主题类接口、展示接口
package com.softline.observer;
public interface Observer {
public void update(float temp);
}
package com.softline.observer;
public interface ISubject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObserver();
}
package com.softline.observer;
public interface IDisplayElement {
public void display();
}
主题实现类
package com.softline.observer;
import java.util.ArrayList;
public class WeatherStation implements ISubject {
private ArrayList<Observer> observers;
private float temp;
public WeatherStation(){
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer observer) {
// TODO Auto-generated method stub
if(!observers.contains(observer))
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
// TODO Auto-generated method stub
int i = observers.indexOf(observer);
if(i>=0)
observers.remove(i);
}
@Override
public void notifyObserver() {
// TODO Auto-generated method stub
for(int i=0;i<observers.size();i++){
Observer observer = (Observer)observers.get(i);
observer.update(temp);
}
}
public void setMeasurements(float temp){
this.temp = temp;
System.out.println("气象站的温度为:"+temp+"0C");
notifyObserver();
}
}
展示类
package com.softline.observer;
public class Display implements Observer,IDisplayElement {
private float temp;
private ISubject weatherStation;
public Display(ISubject weatherStation){
this.weatherStation=weatherStation;
weatherStation.registerObserver(this);
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("当前温度是:"+temp+"0C");
}
@Override
public void update(float temp) {
// TODO Auto-generated method stub
this.temp=temp;
display();
}
}
客户端
package com.softline.observer;
public class Client {
public static void main(String[] args) {
WeatherStation ws = new WeatherStation();
Display diaplay = new Display(ws);
ws.setMeasurements(23);
ws.setMeasurements(24);
ws.setMeasurements(25);
}
}
四、迭代子模式
定义:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象内部表示。
使用场景:当访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑使用迭代器模式。需要对聚集有多种方式遍历时,可以考虑使用迭代器模式。
示意图:
实例:
定义Iterator接口、IContainer接口
package com.softline.Iterator;
public interface Iterator {
public Object first();
public Object previous();
public Object next();
public boolean hasNext();
}
package com.softline.Iterator;
public abstract class IContainer {
public abstract Iterator iterator();
public abstract void put(Object object);
}
定义对应的实现类:
package com.softline.Iterator;
import java.util.List;
public class MyIterator implements Iterator {
private List<Object> list;
private int index = 0;
public MyIterator(List<Object> list){
this.list = list;
}
@Override
public Object first() {
// TODO Auto-generated method stub
if(this.list.size()<=0){
return null;
}else{
return this.list.get(0);
}
}
@Override
public Object previous() {
// TODO Auto-generated method stub
if((this.index-1)<0){
return null;
}else{
return this.list.get(index--);
}
}
@Override
public Object next() {
// TODO Auto-generated method stub
if(this.index >=this.list.size()){
return null;
}else{
return this.list.get(index++);
}
}
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
if(this.index<this.list.size()){
return true;
}
return false;
}
}
package com.softline.Iterator;
import java.util.ArrayList;
import java.util.List;
public class MyContainer extends IContainer {
private List<Object> list;
public MyContainer(){
this.list = new ArrayList<Object>();
}
@Override
public Iterator iterator() {
// TODO Auto-generated method stub
return new MyIterator(list);
}
@Override
public void put(Object object) {
// TODO Auto-generated method stub
this.list.add(object);
}
}
定义测试客户端
package com.softline.Iterator;
public class Client {
public static void main(String[] args) {
MyContainer myContainer = new MyContainer();
myContainer.put("1");
myContainer.put("22");
myContainer.put("333");
Iterator iterator = myContainer.iterator();
while(iterator.hasNext()){
System.out.println(String.valueOf(iterator.next()));
}
}
}
五、责任链模式
定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递改请求,知道有个对象处理它为止。
使用场景:当客户提出一个请求时,请求是沿链传递直至有一个ConcretreHandler对象负责处理它。接受者和发送者都没有明确的信息,且链中的自己并不知道链的结构。结果是职责链可简化对象的相互连接,他们仅需保持一个指向其后继者的引用,而不需要保持他们候选接受者的引用。可以随时的增加或处理一个请求的结构。增强了给对象指派职责的灵活性。一个请求极有可能到了请求的末端都得不到处理,或者因为没有正确的配置而得不到处理。
示意图:
实例:
责任链接口
package com.softline.responsibility;
public abstract class LeaderHandler {
private LeaderHandler hander = null;
public abstract void disposeLeave();
public LeaderHandler setHandler(LeaderHandler hander){
this.hander=hander;
return this.hander;
}
protected void doChain(){
if(this.hander!=null){
this.hander.disposeLeave();
}
}
}
责任链实现类
package com.softline.responsibility;
public class HeadHandler extends LeaderHandler {
@Override
public void disposeLeave() {
// TODO Auto-generated method stub
System.out.println("处理车的Head!");
this.doChain();
}
}
package com.softline.responsibility;
public class BodyHandler extends LeaderHandler {
@Override
public void disposeLeave() {
// TODO Auto-generated method stub
System.out.println("处理身体body!");
this.doChain();
}
}
package com.softline.responsibility;
public class TailHandler extends LeaderHandler {
@Override
public void disposeLeave() {
// TODO Auto-generated method stub
System.out.println("处理结尾!");
this.doChain();
}
}
客户端
package com.softline.responsibility;
public class Client {
public static void main(String[] args) {
LeaderHandler headHandler = new HeadHandler();
LeaderHandler bodyHandler = new BodyHandler();
LeaderHandler tailHandler = new TailHandler();
headHandler.setHandler(bodyHandler).setHandler(tailHandler);
headHandler.disposeLeave();
}
}
window:
处理车的Head!
处理身体body!
处理结尾!
六、命令模式
定义:将一个请求封装为一个对象,从而使你可以使用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作。
使用场景:他能较容易的设计一个命令队列;在需要的情况下,可以较容易的将命令记入日志;允许接受请求的一方决定是否要否决请求。可以容易的实现对请求的撤销重做;由于加进新的具体的命令类而不影响其他类,因此增加新的命令类很容易。命令模式把请求一个对象与知道怎么执行一个操作的对象分隔开。
敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构去实现这个模式并不困难,只有在真正需要如撤销、恢复操作等功能时,把原来的模式重构成命令模式才有意义。
示意图:
实例:
定义家电接口,命令接口
package com.softline.Command;
public interface ICommand {
public void execute();
public void undo();
}
package com.softline.Command;
public interface IHouseholdApplication {
public void on();
public void off();
}
定义家电实现类
package com.softline.Command;
public class Light implements IHouseholdApplication {
@Override
public void on() {
// TODO Auto-generated method stub
System.out.println("light on");
}
@Override
public void off() {
// TODO Auto-generated method stub
System.out.println("light off");
}
}
package com.softline.Command;
public class TV implements IHouseholdApplication {
@Override
public void on() {
// TODO Auto-generated method stub
System.out.println("TV on");
}
@Override
public void off() {
// TODO Auto-generated method stub
System.out.println("TV off");
}
}
定义命令实现类
package com.softline.Command;
public class LightCommand implements ICommand {
private IHouseholdApplication application;
public LightCommand(IHouseholdApplication application){
this.application=application;
}
@Override
public void execute() {
// TODO Auto-generated method stub
application.on();
}
@Override
public void undo() {
// TODO Auto-generated method stub
application.off();
}
}
package com.softline.Command;
public class TVCommand implements ICommand {
private IHouseholdApplication application;
public TVCommand(IHouseholdApplication application){
this.application=application;
}
@Override
public void execute() {
// TODO Auto-generated method stub
application.on();
}
@Override
public void undo() {
// TODO Auto-generated method stub
application.off();
}
}
定义命令实现类
package com.softline.Command;
import java.util.ArrayList;
import java.util.List;
public class Phone {
private List<ICommand> list;
public Phone(){
this.list = new ArrayList<ICommand>();
}
public void setCommand(ICommand command){
this.list.add(command);
}
public void onButtonWasPushed(int index){
list.get(index).execute();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Phone phone = new Phone();
ICommand lightCommand = new LightCommand(new Light());
ICommand tvCommand = new TVCommand(new TV());
phone.setCommand(lightCommand);
phone.setCommand(tvCommand);
phone.onButtonWasPushed(0);
phone.onButtonWasPushed(1);
}
}
windows:
light on
TV on
七、备忘录模式
定义:在不破坏封装性的前提下,捕获一个对象内部的状态,并在这个对象之外保存这个状态。这样以后就可将改对象恢复到原先保存的状态。
使用场景:要保存的细节给封装在了Memento中,哪一天要更改保存的细节也不影响客户端了。Memento模式比较适用于比较复杂的,但需要维护或记录属性的历史的类,或者众多属性中的一小部分,Originator可以根据保存的Memento信息还原到前一状态。如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的的状态。使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来。当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
示意图:
“白箱”备忘录实例:
定义备忘录类、记录类、发起者类
package com.softline.Memento;
public class Memento {
private String state;
public Memento(String state) {
super();
this.state = state;
System.out.println("备忘录保存当前的状态:"+state);
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
package com.softline.Memento;
public class CareTaker {
private Memento memento;
public Memento getMemento(){
return this.memento;
}
public void saveMemento(Memento memento){
this.memento=memento;
}
}
package com.softline.Memento;
public class Originator {
private String state = "0";
public Memento createMemento(){
return new Memento(state);
}
public void restoreMemento(Memento memento){
this.state = memento.getState();
}
public String getState(){
return this.state;
}
public void setState(String state){
this.state = state;
System.out.println("当前状态:"+this.state);
}
}
定义测试类
package com.softline.Memento;
public class Client {
public static void main(String[] args) {
Originator o = new Originator();
CareTaker c = new CareTaker();
o.setState("on");
c.saveMemento(o.createMemento());
o.setState("off");
o.restoreMemento(c.getMemento());
System.out.println(o.getState());
}
}
windows:
当前状态:on
备忘录保存当前的状态:on
当前状态:off
on
“黑箱”备忘录实例:
定义备忘录类、记录类、发起者类
package com.softline.Memento2;
public interface MementoIF {
}
package com.softline.Memento2;
public class Memento implements MementoIF{
private String state;
public Memento(String state) {
super();
this.state = state;
System.out.println("备忘录保存当前的状态:"+state);
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
package com.softline.Memento2;
public class CareTaker {
private MementoIF memento;
public MementoIF getMemento(){
return this.memento;
}
public void saveMemento(MementoIF memento){
this.memento=memento;
}
}
package com.softline.Memento2;
public class Originator {
private String state = "0";
public MementoIF createMemento(){
return new Memento(state);
}
public void restoreMemento(MementoIF memento){
this.setState(((Memento)memento).getState());
}
public String getState(){
return this.state;
}
public void setState(String state){
this.state = state;
System.out.println("当前状态:"+this.state);
}
}
客户端
package com.softline.Memento2;
public class Client {
public static void main(String[] args) {
Originator o = new Originator();
CareTaker c = new CareTaker();
o.setState("on");
c.saveMemento(o.createMemento());
o.setState("off");
o.restoreMemento(c.getMemento());
System.out.println(o.getState());
}
}
备忘录模式与命令模式结合实例:
命令类、备忘录类、操作类接口,命令类抽象类
package com.softline.MementoAndCommand;
public interface ICommand {
public void execute();
public void undo(IMemento m);
public void redo(IMemento m);
public IMemento createMemento();
}
package com.softline.MementoAndCommand;
public interface IMemento {
}
package com.softline.MementoAndCommand;
public interface IOperationApi {
public int getResult();
public void add(int num);
public void substract(int num);
public IMemento createMemto();
public void setMemento(IMemento memento);
}
package com.softline.MementoAndCommand;
public abstract class AbstractCommand implements ICommand{
protected IOperationApi operation = null;
public void setOperation(IOperationApi operation){
this.operation=operation;
}
@Override
public void execute(){}
@Override
public void undo(IMemento memento){
this.operation.setMemento(memento);
}
@Override
public void redo(IMemento memento){
this.operation.setMemento(memento);
}
@Override
public IMemento createMemento(){
return this.operation.createMemto();
}
}
加法命令、减法命令、操作类实现类
package com.softline.MementoAndCommand;
public class AddCommand extends AbstractCommand {
private int openNum;
public AddCommand(int openNum){
this.openNum=openNum;
}
@Override
public void execute(){
this.operation.add(openNum);
}
}
package com.softline.MementoAndCommand;
public class SubstractCommand extends AbstractCommand{
private int opeNum;
public SubstractCommand(int opeNum){
this.opeNum=opeNum;
}
@Override
public void execute(){
this.operation.substract(opeNum);
}
}
package com.softline.MementoAndCommand;
public class OperationImpl implements IOperationApi {
private int result;
@Override
public int getResult() {
// TODO Auto-generated method stub
return this.result;
}
@Override
public void add(int num) {
// TODO Auto-generated method stub
this.result+=num;
}
@Override
public void substract(int num) {
// TODO Auto-generated method stub
this.result-=num;
}
@Override
public IMemento createMemto() {
// TODO Auto-generated method stub
return new MementoImpl(this.result);
}
@Override
public void setMemento(IMemento memento) {
// TODO Auto-generated method stub
this.result = ((MementoImpl)memento).getResult();
}
private static class MementoImpl implements IMemento{
private int result = 0;
public MementoImpl(int result){
this.result=result;
}
public int getResult(){
return this.result;
}
}
}
计算器类、客户端
package com.softline.MementoAndCommand;
import java.util.ArrayList;
import java.util.List;
public class Caculator {
private List<ICommand> undoCommands = new ArrayList<ICommand>();
private List<ICommand> redoCommands = new ArrayList<ICommand>();
private List<IMemento[]> undoMementos = new ArrayList<IMemento[]>();
private List<IMemento[]> redoMementos = new ArrayList<IMemento[]>();
private ICommand addCommand;
private ICommand substractCommand;
public void setSubstractCommand(ICommand substractCommand){
this.substractCommand=substractCommand;
}
public void setAddCommand(ICommand addCommand){
this.addCommand=addCommand;
}
public void addPressed(){
IMemento m1 = this.addCommand.createMemento();
this.addCommand.execute();
undoCommands.add(addCommand);
IMemento m2 = this.addCommand.createMemento();
this.undoMementos.add(new IMemento[]{m1,m2});
}
public void substractPressed(){
IMemento m1 = this.substractCommand.createMemento();
this.substractCommand.execute();
undoCommands.add(this.substractCommand);
IMemento m2 = this.substractCommand.createMemento();
this.undoMementos.add(new IMemento[]{m1,m2});
}
public void undoPressed(){
if(undoCommands.size()>0){
ICommand cmd = undoCommands.get(undoCommands.size()-1);
IMemento[] ms = undoMementos.get(undoCommands.size()-1);
cmd.undo(ms[0]);
redoCommands.add(cmd);
redoMementos.add(ms);
undoCommands.remove(cmd);
undoMementos.remove(ms);
}else{
System.out.println("没有可以撤销的操作");
}
}
public void redoPressed(){
if(redoCommands.size()>0){
ICommand cmd = redoCommands.get(redoCommands.size()-1);
IMemento[] ms = redoMementos.get(redoCommands.size()-1);
cmd.redo(ms[1]);
undoCommands.add(cmd);
undoMementos.add(ms);
redoCommands.remove(cmd);
redoMementos.remove(ms);
}else{
System.out.println("没有可以恢复的命令");
}
}
}
package com.softline.MementoAndCommand;
public class Client {
public static void main(String[] args) {
IOperationApi operation = new OperationImpl();
AddCommand addcmd = new AddCommand(5);
SubstractCommand substractCmd = new SubstractCommand(2);
addcmd.setOperation(operation);
substractCmd.setOperation(operation);
Caculator caculator = new Caculator();
caculator.setAddCommand(addcmd);
caculator.setSubstractCommand(substractCmd);
caculator.addPressed();
System.out.println("一次加法运算后的结果"+operation.getResult());
caculator.substractPressed();
System.out.println("一次减法运算后的结果"+operation.getResult());
caculator.undoPressed();
System.out.println("一次撤销后的结果"+operation.getResult());
caculator.undoPressed();
System.out.println("再一次撤销后的结果"+operation.getResult());
caculator.redoPressed();
System.out.println("一次恢复后的结果"+operation.getResult());
caculator.redoPressed();
System.out.println("再一次恢复后的结果"+operation.getResult());
}
}
windows:
一次加法运算后的结果5
一次减法运算后的结果3
一次撤销后的结果5
再一次撤销后的结果0
一次恢复后的结果5
再一次恢复后的结果3
七、状态模式
定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
使用场景:状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的逻辑简单化。将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易的增加新的状态和转换。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。当一个对象的行为取决于他的状态,并且他必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
示意图:
实例:
状态类接口以及实现类
package com.softline.state;
public interface ITVState {
public void channelUp();
public void channelDown();
public void volumeUp();
public void volumeDown();
}
package com.softline.state;
public class TVOnState implements ITVState {
@Override
public void channelUp() {
// TODO Auto-generated method stub
System.out.println("增加频道");
}
@Override
public void channelDown() {
// TODO Auto-generated method stub
System.out.println("减少频道");
}
@Override
public void volumeUp() {
// TODO Auto-generated method stub
System.out.println("增加音量");
}
@Override
public void volumeDown() {
// TODO Auto-generated method stub
System.out.println("减小音量");
}
}
package com.softline.state;
public class TVDownState implements ITVState {
@Override
public void channelUp() {
// TODO Auto-generated method stub
}
@Override
public void channelDown() {
// TODO Auto-generated method stub
}
@Override
public void volumeUp() {
// TODO Auto-generated method stub
}
@Override
public void volumeDown() {
// TODO Auto-generated method stub
}
}
状态类控制器及客户端
package com.softline.state;
public class TVController {
private ITVState state;
public void setTVState(ITVState state){
this.state=state;
}
public void powerOn(){
this.setTVState(new TVOnState());
System.out.println("开启电视");
}
public void powerOff(){
this.setTVState(new TVDownState());
System.out.println("关闭电视");
}
public void channelUp(){
state.channelUp();
}
public void channelDown(){
state.channelDown();
}
public void volumeUp(){
state.volumeUp();
}
public void volumeDown(){
state.volumeDown();
}
}
package com.softline.state;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
TVController control = new TVController();
control.powerOn();
control.channelUp();
control.channelDown();
control.volumeUp();
control.volumeDown();
control.powerOff();
control.channelUp();
}
}
windows:
开启电视
增加频道
减少频道
增加音量
减小音量
关闭电视
七、访问者模式
定义:表示一个作用与某对象结构中各元素的操作。它使你可以不改变各元素类的前提下定义作用于这些元素的新操作。
使用场景:访问模式适用于数据结构相对稳定的系统,他把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式的目的是要把处理从数据结构分离出来,如果系统有比较稳定的数据结构,又有易于变化的算法,使用访问者模式比较合适。访问者模式的有点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。
示意图:
实例:
账单接口及实现类
package com.softline.visitor;
public interface IBill {
public void accept(IAccountBookView bookView);
}
package com.softline.visitor;
public class IncomeBill implements IBill {
private double amount;
private String item;
public IncomeBill(double amount,String item){
this.amount=amount;
this.item=item;
}
@Override
public void accept(IAccountBookView bookView) {
// TODO Auto-generated method stub
bookView.view(this);
}
public double getAmount(){
return amount;
}
public String getItem(){
return item;
}
}
package com.softline.visitor;
public class ConsumeBill implements IBill {
private double amount;
private String item;
public ConsumeBill(double amount,String item){
this.amount=amount;
this.item=item;
}
@Override
public void accept(IAccountBookView bookView) {
// TODO Auto-generated method stub
bookView.view(this);
}
public double getAmount(){
return amount;
}
public String getItem(){
return item;
}
}
账单查看接口和实现类
package com.softline.visitor;
public interface IAccountBookView {
public void view(ConsumeBill bill);
public void view(IncomeBill bill);
}
package com.softline.visitor;
public class Boss implements IAccountBookView {
private double totalIncome;
private double totalConsume;
@Override
public void view(ConsumeBill bill) {
// TODO Auto-generated method stub
totalConsume+=bill.getAmount();
}
@Override
public void view(IncomeBill bill) {
// TODO Auto-generated method stub
totalIncome+=bill.getAmount();
}
public double getTotalIncome(){
System.out.println("老板查看一共收入多少,数目是:"+totalIncome);
return totalIncome;
}
public double getTotalConsume(){
System.out.println("老板查看一共花费多少,数目是:"+totalConsume);
return totalConsume;
}
}
package com.softline.visitor;
public class CPA implements IAccountBookView {
@Override
public void view(ConsumeBill bill) {
// TODO Auto-generated method stub
if (bill.getItem().equals("工资")) {
System.out.println("注会查看账本时,如果单子的消费目的是发工资,则注会会查看有没有交个人所得税。");
}
}
@Override
public void view(IncomeBill bill) {
// TODO Auto-generated method stub
System.out.println("注会查看账本时,只要是收入,注会都要查看公司交税了没。");
}
}
账单和客户端
package com.softline.visitor;
import java.util.ArrayList;
import java.util.List;
public class AccountBook {
private List<IBill> billList = new ArrayList<IBill>();
public void addBill(IBill bill){
billList.add(bill);
}
public void show(IAccountBookView viewer){
for(IBill bill:billList){
bill.accept(viewer);
}
}
}
package com.softline.visitor;
public class Client {
public static void main(String[] args) {
AccountBook accountBook = new AccountBook();
//添加两条收入
accountBook.addBill(new IncomeBill(10000, "卖商品"));
accountBook.addBill(new IncomeBill(12000, "卖广告位"));
//添加两条支出
accountBook.addBill(new ConsumeBill(1000, "工资"));
accountBook.addBill(new ConsumeBill(2000, "材料费"));
IAccountBookView boss = new Boss();
IAccountBookView cpa = new CPA();
//两个访问者分别访问账本
accountBook.show(boss);
accountBook.show(cpa);
((Boss) boss).getTotalConsume();
((Boss) boss).getTotalIncome();
}
}
windows:
注会查看账本时,只要是收入,注会都要查看公司交税了没。
注会查看账本时,只要是收入,注会都要查看公司交税了没。
注会查看账本时,如果单子的消费目的是发工资,则注会会查看有没有交个人所得税。
老板查看一共花费多少,数目是:3000.0
老板查看一共收入多少,数目是:22000.0
八、中介模式
定义:用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互。
使用场景:中介模式很容易在系统中应用,也很容易在系统中误用。当系统出现了‘多对多’交互复杂的对象群时,不要急于使用中介模式,而要先反思你系统在设计上是不是合理。Mediator的出现减少了各个colleage的耦合,使得可以独立地改变和复用各个Colleague类和Mediator。由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从各自本身的行为转移到他们之间的交互上来,也就是站在一个更加宏观的角度看待系统。由于ConcreteMediator控制了集中化,于是就把交互的复杂性变为了中介的复杂性,这就使得中介者会变得比任何一个ConcreteColleague都复杂。中介模式一般用于一组定义良好但是复杂的方式进行通信的场合。以及想定制一个分布在多个类中的行为,而不像生成太多子类的行为。
示意图:
实例:
定义抽象类和中介类
package com.softline.mediator;
public abstract class AbstractPerson {
protected AbstractMediator mediator;
protected String name;
public AbstractPerson(AbstractMediator mediator,String name){
this.mediator=mediator;
this.name=name;
}
public void setMediator(AbstractMediator mediator){
this.mediator=mediator;
}
protected abstract void sendMessage(String msg);
protected abstract void getMessage(String msg);
}
package com.softline.mediator;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractMediator {
protected List<AbstractPerson> landlordList = new ArrayList<AbstractPerson>();
protected List<AbstractPerson> renterList = new ArrayList<AbstractPerson>();
public void registerLandlord(AbstractPerson landLord) {
landlordList.add(landLord);
}
public void registerRenter(AbstractPerson renter){
renterList.add(renter);
}
public abstract void operation(AbstractPerson person, String message);
}
定义抽象类实现类和中介类实现类
package com.softline.mediator;
public class LandLord extends AbstractPerson {
public LandLord(AbstractMediator mediator,String name){
super(mediator,name);
}
@Override
protected void sendMessage(String msg) {
// TODO Auto-generated method stub
super.mediator.operation(this, msg);
}
@Override
protected void getMessage(String msg) {
// TODO Auto-generated method stub
System.out.println("房东"+super.name+"收到中介发来的消息"+msg);
}
}
package com.softline.mediator;
public class Renter extends AbstractPerson {
public Renter(AbstractMediator mediator,String name){
super(mediator,name);
}
@Override
protected void sendMessage(String msg) {
// TODO Auto-generated method stub
super.mediator.operation(this, msg);
}
@Override
protected void getMessage(String msg) {
// TODO Auto-generated method stub
System.out.println("求租者"+super.name+"收到中介发来的消息"+msg);
}
}
package com.softline.mediator;
public class HouseMediator extends AbstractMediator {
@Override
public void operation(AbstractPerson person, String message) {
// TODO Auto-generated method stub
// 如果是租房者,就把租房者的需求信息传递给注册了的房东们
if (person instanceof Renter) {
for (AbstractPerson landlord : landlordList) {
landlord.getMessage(message);
}
} else if (person instanceof LandLord) {
// 如果是房东,就把房东的出租消息传递给注册了的求租者
for (AbstractPerson renter : renterList) {
renter.getMessage(message);
}
}
}
}
客户端
package com.softline.mediator;
public class Client {
public static void main(String[] args) {
AbstractMediator mediator = new HouseMediator();
AbstractPerson landlordA, landlordB, renter;
landlordA = new LandLord(mediator, "a");
landlordB = new LandLord(mediator, "b");
renter = new Renter(mediator, "小吕");
mediator.registerLandlord(landlordA);
mediator.registerLandlord(landlordB);
mediator.registerRenter(renter);
renter.sendMessage("想在四惠东附近租套一居室,加个1500");
landlordA.sendMessage("在四惠东附近有一套两居室要出租,租金3000,联系电话0101010101001");
}
}
windows:
房东房东a收到中介发来的消息想在四惠东附近租套一居室,加个1500
房东房东b收到中介发来的消息想在四惠东附近租套一居室,加个1500
求租者小吕收到中介发来的消息在四惠东附近有一套两居室要出租,租金3000,联系电话0101010101001
九、解释器模式
定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
使用场景:如果一种特定问题发生的频率足够高,那么可能就值得将该问题的各实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。当一个语言需要解释执行并且你可将该语言中的句子表示为抽象语法树时,可使用解释器模式。解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。
示意图:
实例:
定义接口、抽象类及实现类
package com.softline.interpreter;
public interface INode {
public int interpret();
}
package com.softline.interpreter;
public abstract class AbstractSysbolNode implements INode {
protected INode left;
protected INode right;
public AbstractSysbolNode(INode left,INode right){
this.left=left;
this.right=right;
}
}
package com.softline.interpreter;
public class ValueNode implements INode {
private int value;
public ValueNode(int value){
this.value=value;
}
@Override
public int interpret() {
// TODO Auto-generated method stub
return this.value;
}
}
package com.softline.interpreter;
public class ModNode extends AbstractSysbolNode {
public ModNode(INode left, INode right) {
super(left, right);
// TODO Auto-generated constructor stub
}
@Override
public int interpret() {
// TODO Auto-generated method stub
return super.left.interpret() % super.right.interpret();
}
}
package com.softline.interpreter;
public class MulNode extends AbstractSysbolNode {
public MulNode(INode left, INode right) {
super(left, right);
// TODO Auto-generated constructor stub
}
@Override
public int interpret() {
// TODO Auto-generated method stub
return left.interpret()*right.interpret();
}
}
定义计算器以及客户端
package com.softline.interpreter;
import java.util.Stack;
public class Calculator {
private String statement;
private INode node;
public void build(String statement){
INode left=null,right=null;
Stack stack=new Stack();
String[] statementArr=statement.split(" ");
for(int i=0;i<statementArr.length;i++){
if(statementArr[i].equalsIgnoreCase("*")){
left=(INode)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new MulNode(left,right));
}
else if(statementArr[i].equalsIgnoreCase("/")){
left=(INode)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new DivNode(left,right));
}
else if(statementArr[i].equalsIgnoreCase("%")){
left=(INode)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new ModNode(left,right));
}
else{
stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
}
}
this.node=(INode)stack.pop();
}
public int compute(){
return node.interpret();
}
}
package com.softline.interpreter;
public class Client {
public static void main(String[] args) {
String statement = "3 * 2 * 4 / 6 % 5";
Calculator calculator = new Calculator();
calculator.build(statement);
int result = calculator.compute();
System.out.println(statement + " = " + result);
}
}
windows:
3 * 2 * 4 / 6 % 5 = 4