设计模式之行为型模式

    xiaoxiao2021-04-15  238

    一、简介

    行为型模式(Behavioral Pattern)用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。

    职责链模式 Chain of Responsibility :避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

    使用频率:★★☆☆☆

    命令模式 Command Pattern :将一组行为抽象为对象,实现二者之间的松耦合。

    使用频率:★★★★☆

    解释器模式 Interpreter Pattern:定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的 “语言” 是指使用规定格式和语法的代码。

    使用频率:★☆☆☆☆

    迭代器模式 Iterator Pattern :提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

    使用频率:★★★★★

    中介者模式 Mediator Pattern :用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式。

    使用频率:★★☆☆☆

    备忘录模式 Memento Pattern :在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

    使用频率:★★☆☆☆

    观察者模式 Observer Pattern :定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

    使用频率:★★★★★

    状态模式 State Pattern:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

    使用频率:★★★☆☆

    策略模式 Strategy Pattern :定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。

    使用频率:★★★★☆

    模板方法模式 Template Method Pattern :定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法模式是一种基于继承的代码复用技术。

    使用频率:★★★☆☆

    访问者模式 Visitor Pattern :提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

    使用频率:★☆☆☆☆

    二、职责链模式

    一个商店老板能处理小于0.5的优惠需求,销售经理能处理小于0.2优惠需求,销售员能处理小于0.1优惠需求,可以使用职责链模式:

    2.1、定义抽象类

    //处理顾客打折请求的Handle public abstract class PriceHandle { protected PriceHandle priceHandle; //传递请求 public void setPriceHandle(PriceHandle priceHandle) { this.priceHandle = priceHandle; } public PriceHandle getPriceHandle() { return priceHandle; } //处理打折申请 public abstract void discount(double discount); }

    2.2、定义具体实现类

    老板类(能处理0.5以下优惠)

    //老板 public class Boss extends PriceHandle{ @Override public void discount(double discount) { if(discount<0.5){ System.out.println("老板处理了打折,折扣为:"+discount); }else{ System.out.println("老板拒绝了打折,折扣为:"+discount); } } }

    销售经理类(能处理0.2以下优惠)

    //销售经理 可以处理20%以内的折扣 public class Manager extends PriceHandle{ @Override public void discount(double discount) { if(discount<0.2){ System.out.println("销售经理处理了打折,折扣为:"+discount); }else{ if(priceHandle!=null) { //交给老板处理 priceHandle.discount(discount); }else { //老板不在 拒绝折扣 System.out.println("销售经理拒绝了打折,折扣为:"+discount); } } } }

    销售员类(能处理0.1以下优惠)

    //销售员 可以处理10%以内的折扣 public class Market extends PriceHandle{ @Override public void discount(double discount) { if(discount<0.1){ System.out.println("销售员处理了打折,折扣为:"+discount); }else{ if(priceHandle!=null) { //交给销售经理处理 priceHandle.discount(discount); }else { //销售经理不在 拒绝折扣 System.out.println("销售员拒绝了打折,折扣为:"+discount); } } } }

    顾客类

    //顾客 public class Customer { private PriceHandle pHandle; public void setPHandle(PriceHandle pHandle) { this.pHandle = pHandle; } public void discountReq(double discount){ if(pHandle!=null){ pHandle.discount(discount); } } }

    2.3、使用职责链模式

    //顾客 Customer customer = new Customer(); //老板 Boss boss = new Boss(); //销售经理 Manager manager = new Manager(); //销售员 Market market = new Market(); //顾客将打折请求给销售员处理 customer.setPHandle(market); //销售员把打折请求给销售经理处理 market.setPriceHandle(manager); //销售经理把打折请求给老板处理 manager.setPriceHandle(boss); customer.discountReq(0.09);//销售员处理了打折,折扣为:0.09 customer.discountReq(0.12);//销售经理处理了打折,折扣为:0.12 customer.discountReq(0.23);//老板处理了打折,折扣为:0.23 customer.discountReq(0.5);//老板拒绝了打折,折扣为:0.5

    三、命令模式

    3.1、定义接口和命令执行者

    //命令接口 public interface Command { void command(); }

    命令执行者

    public class Receiver { void receiver(){ System.out.println("接收命令,并执行"); } }

    3.2、定义具体实现和命令调用者

    //命令具体实现 public class RealCommand implements Command { private Receiver receiver; public RealCommand(Receiver receiver) { this.receiver = receiver; } @Override public void command() { if (receiver != null) { receiver.receiver(); } } }

    命令调用者

    //调用命令类 public class Invoker { private Command command; public Invoker(Command command) { this.command = command; } //执行命令 void invoke() { if(command!=null) { command.command(); } } }

    3.3、使用命令模式

    //命令执行者 Receiver receiver = new Receiver(); //将命令执行者添加指挥者中 Command command = new RealCommand(receiver); //将命令指挥者添加到调用者中 Invoker invoker = new Invoker(command); //调用者下发命令 invoker.invoke();//接收命令,并执行

    四、解释器模式

    4.1、定义接口

    //解释器接口 public interface Expression { //解释器 boolean interpret(String context); }

    4.2、定义具体实现

    并且关系解释器

    //并且关系 public class AndExpression implements Expression { private Expression e1; private Expression e2; public AndExpression(Expression e1, Expression e2) { this.e1 = e1; this.e2 = e2; } @Override public boolean interpret(String context) { if (e1 != null && e2 != null) { return e1.interpret(context) && e2.interpret(context); } return false; } }

    或者关系解释器

    //或者关系 public class OrExpression implements Expression { private Expression e1; private Expression e2; public OrExpression(Expression e1, Expression e2) { this.e1 = e1; this.e2 = e2; } @Override public boolean interpret(String context) { if (e1 != null && e2 != null) { return e1.interpret(context) || e2.interpret(context); } return false; } }

    调用者

    public class TerminalExpression implements Expression { private String data; public TerminalExpression(String data) { this.data = data; } @Override public boolean interpret(String context) { if (data != null) { return data.contains(context); } return false; } }

    4.3、使用解释器模式

    Expression e1=new TerminalExpression("ABC"); Expression e2=new TerminalExpression("ABA"); //或者关系,两个其中一个包含"ABC"即可 OrExpression orExpression = new OrExpression(e1, e2); System.out.println(orExpression.interpret("ABC"));//true //并且关系,两个必须都要包含"ABC" AndExpression andExpression = new AndExpression(e1, e2); System.out.println(andExpression.interpret("ABC"));//false

    五、迭代器模式

    5.1、定义接口

    定义书实体

    //书籍类 public class Book { //名称 private String name; //价格 private String price; public Book(String name, String price) { this.name = name; this.price = price; } }

    定义书集合 接口

    //书集合 接口 public interface BookAggregate { //添加书籍 void addCourse(Book book); //移除书籍 void removeCourse(Book book); //获取书籍迭代器 Iterator getBookIterator(); }

    定义迭代器接口

    //迭代器接口 public interface Iterator { // 获取下一本书籍元素 Book nextBook(); //是否是最后一本 boolean isLast(); }

    5.2、定义具体实现

    书籍集合 具体实现类

    //书籍集合 具体实现类 public class BookAggregateImpl implements BookAggregate { private List<Book> bookList = new ArrayList<>(); @Override public void addCourse(Book book) { bookList.add(book); } @Override public void removeCourse(Book book) { bookList.remove(book); } @Override public Iterator getBookIterator() { return new BookIterator(bookList); } }

    具体书籍迭代器

    //具体书籍迭代器 public class BookIterator implements Iterator { private List<Book> bookList; private int position; public BookIterator(List<Book> bookList) { this.bookList = bookList; } @Override public Book nextBook() { if (bookList != null) { Book book = bookList.get(position); position++; return book; } return null; } @Override public boolean isLast() { if (bookList != null) { return position == bookList.size(); } return false; } }

    5.3、使用迭代器模式

    Book book0=new Book("Java开发","78"); Book book1=new Book("Android开发","100"); Book book2=new Book("IOS开发","80"); BookAggregate bookAggregate = new BookAggregateImpl(); bookAggregate.addCourse(book0); bookAggregate.addCourse(book1); bookAggregate.addCourse(book2); Iterator bookIterator = bookAggregate.getBookIterator(); while (!bookIterator.isLast()){ System.out.println(bookIterator.nextBook().toString()); } // Book{name='Java开发', price='78'} // Book{name='Android开发', price='100'} // Book{name='IOS开发', price='80'}

    六、中介者模式

    租客需要租房,可以通过中介找到房主租房子,具体中介者模式实现:

    6.1、定义抽象类

    抽象中介者

    //抽象中介者类 public abstract class Mediator { public abstract void contact(String message,Person person); }

    抽象用户类

    //抽象用户类 public abstract class Person { protected String name; protected Mediator mediator; public Person(String name,Mediator mediator){ this.name = name; this.mediator = mediator; } }

    6.2、定义具体实现

    房主类

    //房主类 public class User1 extends Person { public User1(String name, Mediator mediator) { super(name, mediator); } //与中介者联系 public void contact(String message){ mediator.contact(message, this); } // 获取信息 public void getMessage(String message){ System.out.println("房主:" + name +",获得信息:" + message); } }

    租客类

    //租客类 public class User2 extends Person { public User2(String name, Mediator mediator) { super(name, mediator); } //与中介者联系 public void contact(String message){ mediator.contact(message, this); } // 获取信息 public void getMessage(String message){ System.out.println("租客:" + name +",获得信息:" + message); } }

    中介者具体对象

    //中介者具体对象 public class User extends Mediator { //房主 private User1 user1; //租客 private User2 user2; public void setUser1(User1 user1) { this.user1 = user1; } public void setUser2(User2 user2) { this.user2 = user2; } @Override public void contact(String message, Person person) { if (person == user1) { //房主 user1.getMessage(message); } else { //租客 user2.getMessage(message); } } }

    6.3、使用中介者模式

    User user = new User(); User1 user1 = new User1("张三", user); User2 user2 = new User2("李四", user); user.setUser1(user1); user.setUser2(user2); user1.contact("听说你有房出租"); user2.contact("是的,你需要吗?"); //房主:张三,获得信息:听说你有房出租 //租客:李四,获得信息:是的,你需要吗?

    七、备忘录模式

    7.1、“白箱”备忘录模式

    定义发起人角色类

    //发起人角色类 public class Originator { private String state; //创建一个新的备忘录对象 public Memento createMemento(){ return new Memento(state); } //将发起人角色状态恢复到备忘录对象所记载的状态 public void restoreMemento(Memento memento){ this.state = memento.getState(); } public String getState() { return state; } public void setState(String state) { this.state = state; System.out.println("当前状态:" + this.state); } }

    定义负责人角色类

    //负责人角色类 public class Caretaker { private Memento memento; //获取备忘录 public Memento retrieveMemento(){ return this.memento; } //设置备忘录 public void saveMemento(Memento memento){ this.memento = memento; } }

    定义备忘录对象

    //备忘录对象类 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; } }

    使用"白箱"备忘录模式

    //发起人角色类 Originator o = new Originator(); //负责人角色类 Caretaker c = new Caretaker(); //设置发起人对象的状态 o.setState("ON");//当前状态:ON //创建备忘录对象,并将发起人对象的状态储存起来 c.saveMemento(o.createMemento()); //修改发起人的状态 o.setState("OFF");//当前状态:OFF //恢复发起人对象的状态 o.restoreMemento(c.retrieveMemento()); System.out.println(o.getState());//ON

    7.2、“黑箱”备忘录模式

    定义接口

    //标识接口(窄接口) public interface MementoIF { }

    定义发起人角色类

    //发起人角色类 public class Originator2 { private String state; //创建一个新的备忘录对象 public MementoIF createMemento() { return new Memento2(state); } //将发起人角色状态恢复到备忘录对象所记载的状态 public void restoreMemento(MementoIF memento) { this.state = ((Memento2) memento).getState(); } public String getState() { return state; } public void setState(String state) { this.state = state; System.out.println("当前状态:" + this.state); } //发起人角色类Originator中定义了一个内部的Memento2类,由于此Memento2类的全部接口都是私有的,因此只有它自己和发起人类可以调用 private class Memento2 implements MementoIF { private String state; private Memento2(String state) { this.state = state; } private String getState() { return state; } private void setState(String state) { this.state = state; } } }

    定义负责人角色类

    //负责人角色类 public class Caretaker2 { private MementoIF memento; //获取备忘录 public MementoIF retrieveMemento(){ return this.memento; } //设置备忘录 public void saveMemento(MementoIF memento){ this.memento = memento; } }

    使用"黑箱"备忘录模式

    //发起人角色类 Originator2 o2 = new Originator2(); //负责人角色类 Caretaker2 c2 = new Caretaker2(); //设置发起人对象的状态 o2.setState("ON");//当前状态:ON //创建备忘录对象,并将发起人对象的状态存储起来 c2.saveMemento(o2.createMemento()); //修改发起人对象的状态 o2.setState("OFF");//当前状态:OFF //恢复发起人对象的状态 o2.restoreMemento(c2.retrieveMemento()); System.out.println(o2.getState());//ON

    7.2、多重检查点 备忘录模式

    定义发起人角色类

    //发起人角色类 public class Originator3 { //所有状态集合 private List<String> states; //检查点指数 private int index; public Originator3(){ states = new ArrayList<String>(); index = 0; } //创建一个新的备忘录对象 public Memento3 createMemento(){ return new Memento3(states , index); } //将发起人角色状态恢复到备忘录对象所记载的状态 public void restoreMemento(Memento3 memento){ states = memento.getStates(); index = memento.getIndex(); } //设置状态 public void setState(String state){ states.add(state); index++; } //打印所有状态 public void printStates(){ for(String state : states){ System.out.println(state); } } }

    定义负责人角色类

    //负责人角色类 public class Caretaker3 { private Originator3 o; private List<Memento3> mementos = new ArrayList<Memento3>(); private int current; public Caretaker3(Originator3 o){ this.o = o; current = 0; } //创建一个新的检查点 public int createMemento(){ Memento3 memento = o.createMemento(); mementos.add(memento); return current++; } // 将发起人恢复到某个检查点 public void restoreMemento(int index){ Memento3 memento = mementos.get(index); o.restoreMemento(memento); } //删除某个检查点 public void removeMemento(int index){ mementos.remove(index); } }

    定义备忘录对象

    //备忘录对象类 public class Memento3 { private List<String> states; private int index; public Memento3(List<String> states, int index) { this.states = new ArrayList<String>(states); this.index = index; } public List<String> getStates() { return states; } public int getIndex() { return index; } }

    使用多重检查点备忘录模式

    //发起人角色类 Originator3 o3 = new Originator3(); //负责人角色类 Caretaker3 c3 = new Caretaker3(o3); //设置发起人对象状态 o3.setState("状态A"); //建立一个检查点 c3.createMemento(); //设置发起人对象状态 o3.setState("状态B"); //建立一个检查点 c3.createMemento(); //设置发起人对象状态 o3.setState("状态C"); //建立一个检查点 c3.createMemento(); //打印出所有检查点 o3.printStates(); //状态A //状态B //状态C System.out.println("----恢复到第二个检查点----"); //恢复到第二个检查点 c3.restoreMemento(1); //打印出所有检查点 o3.printStates(); //状态A //状态B

    八、观察者模式

    8.1、定义接口

    观察者接口

    //观察者接口 public interface Observer { //更新消息,当被观察者notifyObserver被调用时,update方法将被触发 void update(String message); }

    被观察者接口

    //被观察者接口 public interface Observerable { //注册观察者 void registerObserver(Observer o); //反注册观察者 void removeObserver(Observer o); //通知观察者更新消息 void notifyObserver(); }

    8.2、定义具体实现

    观察者实现类

    //观察者类(用户) public class User implements Observer { //用户名 private String name; public User(String name) { this.name = name; } @Override public void update(String message) { System.out.println(name + " 收到消息:" + message); } }

    被观察者实现类

    //被观察者具体类(推送消息服务) public class PushObserver implements Observerable { private List<Observer> observerList; private String msg; public PushObserver() { observerList = new ArrayList<>(); } @Override public void registerObserver(Observer o) { observerList.add(o); } @Override public void removeObserver(Observer o) { observerList.remove(o); } @Override public void notifyObserver() { //通知所有已注册的观察者用户 for (Observer observer : observerList) { observer.update(msg); } } //推送一条消息 public void pushMsg(String msg) { this.msg = msg; System.out.println("推送系统推送消息:" + msg); notifyObserver(); } }

    8.3、使用观察者模式

    User user1=new User("张三"); User user2=new User("李四"); PushObserver pushObserver=new PushObserver(); //添加user1用户观察 pushObserver.registerObserver(user1); //添加user2用户观察 pushObserver.registerObserver(user2); //发送消息 pushObserver.pushMsg("今天气温为30摄氏度"); //推送系统推送消息:今天气温为30摄氏度 //张三 收到消息:今天气温为30摄氏度 //李四 收到消息:今天气温为30摄氏度 //移除user1用户观察者,user1将收不到消息 pushObserver.removeObserver(user1); //发送消息 pushObserver.pushMsg("明天气温为10摄氏度"); //推送系统推送消息:明天气温为10摄氏度 //李四 收到消息:明天气温为10摄氏度

    九、状态模式

    9.1、定义接口

    状态上下文

    //状态上下文 public class Context { //当前状态 private State state; //获取当前状态呢 public State getState() { return state; } //设置当前状态 public void setState(State state) { this.state = state; } }

    状态接口

    //定义状态接口 public interface State { //执行操作 void doAction(Context context); }

    9.2、定义具体实现

    启动状态类

    //启动状态类 public class StartState implements State { @Override public void doAction(Context context) { System.out.println("正处于启动状态"); context.setState(this); } }

    停止状态类

    //停止状态类 public class StopState implements State{ @Override public void doAction(Context context) { System.out.println("正处于停止状态"); context.setState(this); } }

    9.3、使用状态模式

    Context context = new Context(); //创建开始状态 State startState = new StartState(); //将开始状态包装在状态上下文中 startState.doAction(context);//正处于启动状态 //在状态上下文中获取当前状态 System.out.println(context.getState() instanceof StartState);//true //创建停止状态 State stopState = new StopState(); //将停止状态包装在状态上下文中 stopState.doAction(context);//正处于停止状态 //在状态上下文中获取当前状态 System.out.println(context.getState() instanceof StopState);//true

    十、策略模式

    10.1、定义接口

    //策略接口类 public interface Strategy { //策略方法 void algorithmInterface(); }

    10.2、定义具体实现

    策略具体实现A

    //具体策略类A public class ConcreteStrategyA implements Strategy { @Override public void algorithmInterface() { System.out.println("具体策略类A实现类策略"); } }

    策略具体实现B

    //具体策略类B public class ConcreteStrategyB implements Strategy { @Override public void algorithmInterface() { System.out.println("具体策略类B实现类策略"); } }

    策略上下文

    //策略上下文类 public class Context { //持有一个具体策略的对象 private Strategy strategy; //构造函数,需要传入一个具体策略对象 public Context(Strategy strategy){ this.strategy = strategy; } //执行策略方法 public void contextInterface(){ strategy.algorithmInterface(); } }

    10.3、使用策略模式

    //具体策略A Strategy concreteStrategyB = new ConcreteStrategyB(); //使用策略上下文包装具体策略A Context contextB=new Context(concreteStrategyB); //调用具体策略 contextB.contextInterface();//具体策略类B实现类策略 //具体策略B Strategy concreteStrategyA = new ConcreteStrategyA(); //使用策略上下文包装具体策略B Context contextA=new Context(concreteStrategyA); //调用具体策略 contextA.contextInterface();//具体策略类A实现类策略

    十一、模板方法模式

    11.1、定义抽象类

    盒子抽象模版类

    //制作盒子模版 public abstract class Box { //开始制作 final void startMake() { //选取材料 seek(); //切割材料 cutting(); //焊接材料 welding(); //打磨抛光外形 polish(); } protected abstract void seek(); protected abstract void cutting(); protected abstract void welding(); void polish() { System.out.println("使用打磨机器打磨完成"); } }

    11.2、定义具体实现

    具体铁盒子

    //铁盒子 public class IronBox extends Box{ @Override protected void seek() { System.out.println("使用木头做材料"); } @Override protected void cutting() { System.out.println("使用普通锯子切割"); } @Override protected void welding() { System.out.println("使用打孔方式相接"); } }

    具体木盒子

    //木头盒子 public class WoodBox extends Box{ @Override protected void seek() { System.out.println("使用钢铁做材料"); } @Override protected void cutting() { System.out.println("使用电锯切割"); } @Override protected void welding() { System.out.println("使用电焊相接"); } }

    11.3、使用模版方法模式

    //铁盒子 Box ironBox = new IronBox(); ironBox.startMake(); //使用木头做材料 //使用普通锯子切割 //使用打孔方式相接 //使用打磨机器打磨完成 //木头盒子 Box woodBox = new WoodBox(); woodBox.startMake(); //使用钢铁做材料 //使用电锯切割 //使用电焊相接 //使用打磨机器打磨完成

    十二、访问者模式

    12.1、定义抽象类

    人类抽象类

    //抽象人类 public abstract class Human { //抽象接受访问 abstract void accept(Visitor visitor); }

    访问方式抽象类

    //抽象的访问方式类 public abstract class Visitor { //访问中国人 public abstract void visitChinese(Chinese chinese); //访问美国人 public abstract void visitAmerican(American american); }

    12.2、定义具体实现

    人类具体实现(中国人)

    //中国人 public class Chinese extends Human { @Override void accept(Visitor visitor) { //中国人处理事件 visitor.visitChinese(this); } }

    人类具体实现(美国人)

    //美国人 public class American extends Human{ @Override void accept(Visitor visitor) { //美国人处理事件 visitor.visitAmerican(this); } }

    具体访问类(吃饭)

    //具体访问类(吃饭) public class EatVisitor extends Visitor { @Override public void visitChinese(Chinese chinese) { System.out.println("中国人使用筷子吃饭"); } @Override public void visitAmerican(American american) { System.out.println("美国人使用刀叉吃饭"); } }

    具体访问类(头发)

    //具体访问类(头发) public class HairVisitor extends Visitor { @Override public void visitChinese(Chinese chinese) { System.out.println("中国人黑色头发"); } @Override public void visitAmerican(American american) { System.out.println("美国人金色头发"); } }

    12.3、使用访问者模式

    //具体访问对象(吃饭) Visitor eatVisitor = new EatVisitor(); //具体访问对象(头发) Visitor hairVisitor = new HairVisitor(); //具体被访问对象(中国人) Human chinese = new Chinese(); //具体被访问对象(美国人) Human american = new American(); //中国人接受访问吃饭的问题 chinese.accept(eatVisitor);//中国人使用筷子吃饭 //中国人接受访问头发的问题 chinese.accept(hairVisitor);//中国人黑色头发 //美国人接受访问吃饭的问题 american.accept(eatVisitor);//美国人使用刀叉吃饭 //美国人接受访问头发的问题 american.accept(hairVisitor);//美国人金色头发

    最新回复(0)