行为型模式,共11种
(1)责任链模式
(2)策略模式
(3)模板方法
(4)状态模式
(5)访问者模式
(6)观察者模式
(7)迭代器模式
(8)命令模式
(9)备忘录模式
(10)中介者模式
(11)解释器模式
责任链模式
将接收者对象连成一条链,并在该链上传递请求对象,直到有一个接收者处理该请求对象。该请求对象事先不知道是由哪一个接收者对象处理的。
public abstract class PriceHandler { //直接后继,用于传递请求 protected PriceHandler successor; public void setSuccessor(PriceHandler successor){ this.successor = successor; } //处理折扣申请 public abstract void processDiscount(float discount); } public class Sales extends PriceHandler { @Override public void processDiscount(float discount) { if(discount <= 0.05) { System.out.format("%s批准了折扣:%.2f ", this.getClass().getName(),discount); } else { successor.processDiscount(discount); } } } public class Manager extends PriceHandler { @Override public void processDiscount(float discount) { if(discount <= 0.3) { System.out.format("%s批准了折扣:%.2f ", this.getClass().getName(),discount); } else { successor.processDiscount(discount); } } } public class CEO extends PriceHandler { @Override public void processDiscount(float discount) { if(discount <= 0.5) { System.out.format("%s批准了折扣:%.2f ", this.getClass().getName(),discount); } else { System.out.format("%s拒绝了折扣:%.2f ", this.getClass().getName(),discount); } } } public class PriceHandlerFactory { //创建PriceHandler的工厂函数 public static PriceHandler createPricHandler() { // TODO Auto-generated method stub PriceHandler sales= new Sales(); PriceHandler manager= new Manager(); PriceHandler ceo= new CEO(); sales.setSuccessor(manager); manager.setSuccessor(ceo); return sales; } } public class Customer { private PriceHandler pricHandler; public void setPriceHandler(PriceHandler pricHandler) { this.pricHandler = pricHandler; } public void requestDiscount(float discount) { pricHandler.processDiscount(discount); } } public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub Customer customer = new Customer(); customer.setPriceHandler(PriceHandlerFactory.createPricHandler()); Random rand = new Random(); for(int i=0;i<10;i++) { System.out.print(i+":"); customer.requestDiscount(rand.nextFloat()); } } }
策略模式
定义了不同的算法(策略),分别封装起来,让他们可以互相替换,即使算法变化了,也不会影响到使用算法的用户
//抽象策略 public interface Action { //学生的动作 void action(); } public class PlayAction implements Action { @Override public void action() { System.out.println("正在玩耍......."); } } public class SleepAction implements Action { @Override public void action() { System.out.println("正在睡觉......"); } } public class Student { // 对策略的引用 private Action action; public Student( Action action){ this.action = action; } // 学生的行为 public void studentAction(){ action.action(); } } public class MainClass { public static void main(String[] args) { // 睡觉的行为 Action sleep = new SleepAction(); // 玩的行为 Action play = new PlayAction(); //小明 Student xiaoming = new Student(sleep); xiaoming.studentAction(); //小明明 Student mingming = new Student(play); mingming.studentAction(); } }
模板方法
一个算法框架涉及到很多步骤,把不变的部分封装在父类,可变的部分让不同的子类去实现,父类中可以包含默认的钩子方法,子类可以选择是否重写该钩子方法
//算法骨架 public abstract class RefreshBeverage { /* * 制备饮料的模板方法 封装了所有子类所遵循的算法框架 */ public final void prepareBeverageTemplate() { // 步骤一 将水煮沸 boilWater(); // 步骤二 泡制饮料 brew(); // 步骤三 将饮料倒入杯中 pourInCup(); if (isCustomerWantsCondiments()) { // 步骤四 加入调味料 addCondiments(); } } /* * Hook 钩子函数,提供一个空的或者默认的实现 子类重写该方法,可以自行决定是否挂钩以及如何挂钩 */ protected boolean isCustomerWantsCondiments() { return true; } // 因为将水煮沸和把饮料倒入杯中对所有子类是共同的行为,所以没必要向子类过多开放,所以方法定义为private,这样我们在进行子类编码时可以减少复杂度。 // 这样不需要关注细枝末节,我们只需要关注我们特定业务的实现,这就是模板方法模式的好处。可以封装变与不变,将不变的固化在高层,隐藏其细节。 private void boilWater() { System.out.println("将水煮沸"); } private void pourInCup() { System.out.println("将饮料倒入杯中"); } /* * 泡制饮料brew()和加入调料品addCondiments()这两个方法我们不知道它们在算法框架中的具体实现,因此定义为抽象方法, * 我们用protected进行修饰, 在子类中可见便于进行重写。 */ protected abstract void brew(); protected abstract void addCondiments(); } /** * 提供制备咖啡的具体实现子类。 具体子类实现延迟步骤,满足特定的业务需求。 * * */ public class Coffee extends RefreshBeverage { protected void brew() { System.out.println("步骤二 用沸水冲泡咖啡"); } protected void addCondiments() { System.out.println("步骤四 加入糖和牛奶"); } } public class Tea extends RefreshBeverage { protected void brew() { System.out.println("步骤二 用80度热水浸泡茶叶5分钟"); } protected void addCondiments() { System.out.println("步骤四 加入柠檬"); } protected boolean isCustomerWantsCondiments() { return false; } } public class MainClass { public static void main(String[] args) { System.out.println("制备咖啡中······"); RefreshBeverage b1 = new Coffee(); b1.prepareBeverageTemplate(); System.out.println("咖啡好了········"); // 制备茶的测试代码 System.out.println(" *********************************"); System.out.println("制备茶水中······"); RefreshBeverage b2 = new Tea(); b2.prepareBeverageTemplate(); System.out.println("茶水好了······"); } }
状态模式
当一个对象的内在状态改变时允许改变其行为,可以简化if-else条件判断
//抽象的状态角色 public interface State { void handle(); } public class FreeState implements State { @Override public void handle() { System.out.println("房间空闲!!!没人住!"); } } public class CheckedInState implements State { @Override public void handle() { System.out.println("房间已入住!请勿打扰!"); } } public class BookedState implements State { @Override public void handle() { System.out.println("房间已预订!别人不能预定!"); } } public class ApartmentContext { private State state; public void setState(State s){ this.state = s; } public State getState() { return state; } public void changeState(State s) { System.out.print("修改状态!==> "); state = s; state.handle(); } } public class MainClass { public static void main(String[] args) { // 获取房间对象 ApartmentContext ctx = new ApartmentContext(); // 设置房间状态 ctx.changeState(new FreeState()); ctx.changeState(new BookedState()); } }
访问者模式
对于数据结构稳定,而作用于数据结构的操作经常变化的时候,可以采用访问者模式,将数据结构和对数据的操作分离
//单个单子的接口(相当于Element) public interface Bill { void accept(Viewer viewer); } //抽象单子类,一个高层次的单子抽象 public abstract class AbstractBill implements Bill{ protected double amount; protected String item; public AbstractBill(double amount, String item) { super(); this.amount = amount; this.item = item; } public double getAmount() { return amount; } public String getItem() { return item; } } //消费的单子 public class ConsumeBill extends AbstractBill{ public ConsumeBill(double amount, String item) { super(amount, item); } public void accept(Viewer viewer) { if (viewer instanceof AbstractViewer) { ((AbstractViewer)viewer).viewConsumeBill(this); return; } viewer.viewAbstractBill(this); } } //收入单子 public class IncomeBill extends AbstractBill{ public IncomeBill(double amount, String item) { super(amount, item); } public void accept(Viewer viewer) { if (viewer instanceof AbstractViewer) { ((AbstractViewer)viewer).viewIncomeBill(this); return; } viewer.viewAbstractBill(this); } } //超级访问者接口(它支持定义高层操作) public interface Viewer{ void viewAbstractBill(AbstractBill bill); } //比Viewer接口低一个层次的访问者接口 public abstract class AbstractViewer implements Viewer{ //查看消费的单子 abstract void viewConsumeBill(ConsumeBill bill); //查看收入的单子 abstract void viewIncomeBill(IncomeBill bill); public final void viewAbstractBill(AbstractBill bill){} } //老板类,查看账本的类之一,作用于最低层次结构 public class Boss extends AbstractViewer{ private double totalIncome; private double totalConsume; //老板只关注一共花了多少钱以及一共收入多少钱,其余并不关心 public void viewConsumeBill(ConsumeBill bill) { totalConsume += bill.getAmount(); } public void viewIncomeBill(IncomeBill bill) { totalIncome += bill.getAmount(); } public double getTotalIncome() { System.out.println("老板查看一共收入多少,数目是:" + totalIncome); return totalIncome; } public double getTotalConsume() { System.out.println("老板查看一共花费多少,数目是:" + totalConsume); return totalConsume; } } //注册会计师类,查看账本的类之一,作用于最低层次结构 public class CPA extends AbstractViewer{ //注会在看账本时,如果是支出,则如果支出是工资,则需要看应该交的税交了没 public void viewConsumeBill(ConsumeBill bill) { if (bill.getItem().equals("工资")) { System.out.println("注会查看是否交个人所得税。"); } } //如果是收入,则所有的收入都要交税 public void viewIncomeBill(IncomeBill bill) { System.out.println("注会查看收入交税了没。"); } } //财务主管类,查看账本的类之一,作用于高层的层次结构 public class CFO implements Viewer { //财务主管对每一个单子都要核对项目和金额 public void viewAbstractBill(AbstractBill bill) { System.out.println("财务主管查看账本时,每一个都核对项目和金额,金额是" + bill.getAmount() + ",项目是" + bill.getItem()); } } //账本类(相当于ObjectStruture) public class AccountBook { //单子列表 private List<Bill> billList = new ArrayList<Bill>(); //添加单子 public void addBill(Bill bill){ billList.add(bill); } //供账本的查看者查看账本 public void show(Viewer viewer){ for (Bill bill : billList) { bill.accept(viewer); } } } public class MainClass { 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, "材料费")); Viewer boss = new Boss(); Viewer cpa = new CPA(); Viewer cfo = new CFO(); //两个访问者分别访问账本 accountBook.show(cpa); accountBook.show(boss); accountBook.show(cfo); ((Boss) boss).getTotalConsume(); ((Boss) boss).getTotalIncome(); } }
观察者模式
在对象之间定义了一对多的依赖,当一个对象改变状态,依赖它的对象会收到通知并自动更新
/*** * 抽象被观察者接口 * 声明了添加、删除、通知观察者方法 * @author jstao * */ public interface Observerable { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObserver(); } /** * 被观察者,也就是微信公众号服务 * 实现了Observerable接口,对Observerable接口的三个方法进行了具体实现 * @author jstao * */ public class WechatServer implements Observerable { //注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程 private List<Observer> list; private String message; public WechatServer() { list = new ArrayList<Observer>(); } @Override public void registerObserver(Observer o) { list.add(o); } @Override public void removeObserver(Observer o) { if(!list.isEmpty()) { list.remove(o); } } //遍历 @Override public void notifyObserver() { for(int i = 0; i < list.size(); i++) { Observer oserver = list.get(i); oserver.update(message); } } public void setInfomation(String s) { this.message = s; System.out.println("微信服务更新消息: " + s); //消息更新,通知所有观察者 notifyObserver(); } } /*** * 抽象观察者 * 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。 * @author jstao * */ public interface Observer { public void update(String message); } /** * 观察者 * 实现了update方法 * @author jstao * */ public class User implements Observer { private String name; private String message; public User(String name) { this.name = name; } @Override public void update(String message) { this.message = message; read(); } public void read() { System.out.println(name + " 收到推送消息: " + message); } } public class MainClass { public static void main(String[] args) { WechatServer server = new WechatServer(); Observer userZhang = new User("ZhangSan"); Observer userLi = new User("LiSi"); Observer userWang = new User("WangWu"); server.registerObserver(userZhang); server.registerObserver(userLi); server.registerObserver(userWang); server.setInfomation("PHP是世界上最好用的语言!"); System.out.println("----------------------------------------------"); server.removeObserver(userZhang); server.setInfomation("JAVA是世界上最好用的语言!"); } }
迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示
//迭代器接口 , 相当与jdk中的iterator public interface MyIterator { boolean hasNext(); Object next(); } //标识接口是可以迭代的,返回一个迭代器,相当与jdk中的iterable public interface MyIterable { MyIterator getMyIterator(); } //具体的聚合对象,相当于ArrayList,HashMap等 public class PlaceContainer implements MyIterable { private String[] places; public PlaceContainer(String[] places) { this.places = places; } private class PlaceIterator implements MyIterator { private int index; @Override public boolean hasNext() { return index < places.length; } @Override public Object next() { return places[index++]; } } @Override public MyIterator getMyIterator() { return new PlaceIterator(); } } public class MainClass { public static void main(String[] args) { String[] places = new String[] { "beijing", "tianjin", "xian", "shanghai", "guangzhou" }; PlaceContainer placeContainer = new PlaceContainer(places); for (MyIterator iterator = placeContainer.getMyIterator(); iterator.hasNext();) { System.out.println(iterator.next()); } } }
命令模式
将请求发送者与接收者解耦,请求发送者通过命令对象来间接引用请求接收者,也可以实现命令的取消和重做
public interface Command { //执行命令对应的操作 public void execute(); //执行撤销命令那个对应的操作 public void undo(); } public class AddCommand implements Command{ //持有接收者对象 private Operation operation = null; //操作的数据,就是要加上的数据 private int num; public void execute(){ this.operation.add(num); } public void undo(){ this.operation.add(-num); } public AddCommand(Operation operation,int num){ this.operation = operation; this.num = num; } } public class SubstractCommand implements Command { private Operation operation = null; private int num; public SubstractCommand(Operation operation,int num){ this.operation = operation; this.num = num; } @Override public void execute() { this.operation.substract(num); } @Override public void undo() { this.operation.substract(-num); } } //请求接收者 public class Operation { private int result ; public int getResult() { return result; } public void setResult(int result) { this.result = result; } public void add(int num) { result += num; } public void substract(int num) { result -= num; } } //请求发送者 public class Caculator { private Command addCommand = null; private Command substractCommand = null; private List<Command> undoCommands = new ArrayList<Command>(); private List<Command> redoCommands = new ArrayList<Command>(); public void setAddCommand(Command addCmd){ this.addCommand = addCmd; } public void setSubstractCommand(Command substractCmd){ this.substractCommand = substractCmd; } public void addPressed(){ this.addCommand.execute(); undoCommands.add(this.addCommand); } public void substractPressed(){ this.substractCommand.execute(); undoCommands.add(this.substractCommand); } public void undoPressed(){ if(this.undoCommands.size()>0){ Command cmd = this.undoCommands.get(this.undoCommands.size()-1); cmd.undo(); this.redoCommands.add(cmd); this.undoCommands.remove(cmd); }else{ System.out.println("没有课撤销的命令"); } } public void redoPressed(){ if(this.redoCommands.size()>0){ Command cmd = this.redoCommands.get(this.redoCommands.size()-1); cmd.execute(); this.undoCommands.add(cmd); this.redoCommands.remove(cmd); }else{ System.out.println("没有课恢复的命令"); } } } public class MainClass { public static void main(String[] args) { Operation operation = new Operation(); AddCommand addCmd = new AddCommand(operation,5); SubstractCommand subCmd = new SubstractCommand(operation,3); Caculator caculator = new Caculator(); caculator.setAddCommand(addCmd); caculator.setSubstractCommand(subCmd); caculator.addPressed(); caculator.substractPressed(); System.out.println(operation.getResult()); caculator.undoPressed(); System.out.println(operation.getResult()); caculator.redoPressed(); System.out.println(operation.getResult()); } }
备忘录
获取一个对象的内部状态,保存该状态,这样以后就可以将该对象恢复至原先保存的状态
public class Memento { public static void main(String[] args) { // 发起人与负责人 Sponsor sponsor = new Sponsor(); // 设置内容 sponsor.setText("abc"); // 保存状态 sponsor.createManager(1); // 修改内容 sponsor.setText("abcd"); // 保存状态 sponsor.createManager(2); // 修改内容 sponsor.setText("abcde"); // 保存状态 sponsor.createManager(3); // 回滚到版本1 sponsor.callBackToVersion(1); System.out.println("第一个版本的内容是:" + sponsor.getText()); // 回滚到版本2 sponsor.callBackToVersion(3); System.out.println("第三个版本的内容是:" + sponsor.getText()); } } // 发起者+负责人 能知道备忘录角色的具体类容,因为备忘录角色是它的私有类 class Sponsor { private String text; private Map<Integer, TextEdit> map = new HashMap<>(); // 每次取出最新的版本 private TextEdit getTextEdit(Integer version) { return map.get(version); } // 保存版本 private void setTextEdit(TextEdit baby, Integer version) { map.put(version, baby); } // 保存状态 public void createManager(Integer version) { TextEdit edit = new TextEdit(text); setTextEdit(edit, version); } // 回滚到指定版本 public void callBackToVersion(Integer version) { text = getTextEdit(version).getText(); } public String getText() { return text; } public void setText(String text) { this.text = text; } // 备忘录角色,被发起者私有 // 注意:此类的所有属性都是私有 private class TextEdit { private String text; private TextEdit(String text) { this.text = text; } private String getText() { return text; } } }
中介者模式
协作一组同事. 那些同事互相之间不会直接沟通, 而是通过中介者
//抽象中介者 public abstract class UnitedNations { protected List<Country> countries = new LinkedList<>(); public void register(Country country) { countries.add(country); } public void remove(Country country) { countries.remove(country); } protected abstract void declare(Country country, String msg); } //具体中介者 class UnitedNationsSecurityCouncil extends UnitedNations { @Override protected void declare(Country country, String msg) { for (Country toCountry : countries) { if (!toCountry.equals(country)) { String name = country.getName(); toCountry.receive(name + "平和的说: " + msg); } } } } //抽象同事 public abstract class Country { protected UnitedNations mediator; private String name; public Country(UnitedNations mediator, String name) { this.mediator = mediator; this.name = name; } public String getName() { return name; } protected abstract void declare(String msg); protected abstract void receive(String msg); } //具体同事 class Iraq extends Country { public Iraq(UnitedNations mediator, String name) { super(mediator, name); } @Override public void declare(String msg) { mediator.declare(this, msg); } @Override public void receive(String msg) { System.out.println("伊拉克接收到: [" + msg + "]"); } } //具体同事 class China extends Country { public China(UnitedNations mediator, String name) { super(mediator, name); } @Override public void declare(String msg) { mediator.declare(this, msg); } @Override public void receive(String msg) { System.out.println("中国接收到: [" + msg + "]"); } } //具体同事 class USA extends Country { public USA(UnitedNations mediator, String name) { super(mediator, name); } @Override public void declare(String msg) { mediator.declare(this, msg); } @Override public void receive(String msg) { System.out.println("美国接收到: [" + msg + "]"); } } public class MainClass { public static void main(String[] args) {
UnitedNations mediator = new UnitedNationsSecurityCouncil(); Country usa = new USA(mediator, "美国"); Country china = new China(mediator, "中国"); Country iraq = new Iraq(mediator, "伊拉克"); mediator.register(usa); mediator.register(china); mediator.register(iraq); usa.declare("我要打伊拉克, 谁管我跟谁急!!!"); System.out.println("----------"); china.declare("我们强烈谴责!!!"); System.out.println("----------"); iraq.declare("来呀, 来互相伤害呀!!!"); } }
解释器模式
按照规定语法进行语句的解析并得到结果
public interface Expression { int interpreter(Context context);// } public abstract class NonTerminalExpression implements Expression { Expression e1, e2; public NonTerminalExpression(Expression e1, Expression e2) { this.e1 = e1; this.e2 = e2; } } public class MinusOperation extends NonTerminalExpression { public MinusOperation(Expression e1, Expression e2) { super(e1, e2); } // 将两个表达式相减 @Override public int interpreter(Context context) { return e1.interpreter(context) - e2.interpreter(context); } } public class PlusOperation extends NonTerminalExpression { public PlusOperation(Expression e1, Expression e2) { super(e1, e2); } // 将两个表达式相加 @Override public int interpreter(Context context) { return e1.interpreter(context) + e2.interpreter(context); } } public class TerminalExpression implements Expression { String variable; public TerminalExpression(String variable) { this.variable = variable; } @Override public int interpreter(Context context) { return Integer.valueOf(variable); } } public class Context { private Map<Expression, Integer> map = new HashMap<>(); public void add(Expression s, Integer value) { map.put(s, value); } public Integer lookup(Expression s) { return map.get(s); } // 构建语法树的主要方法 public static Expression build(String str) { // 主要利用栈来实现 Stack<Expression> objects = new Stack<>(); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); // 遇到运算符号+号时候 if (c == '+') { // 先出栈 Expression pop = objects.pop(); // 将运算结果入栈 objects.push(new PlusOperation(pop, new TerminalExpression(String.valueOf(str.charAt(++i))))); } else if (c == '-') { // 遇到减号类似加号 Expression pop = objects.pop(); objects.push(new MinusOperation(pop, new TerminalExpression(String.valueOf(str.charAt(++i))))); } else { // 遇到非终结符直接入栈(基本就是第一个数字的情况) objects.push(new TerminalExpression(String.valueOf(str.charAt(i)))); } } // 把最后的栈顶元素返回 return objects.pop(); } } public class MainClass { public static void main(String[] args) { String str = "4+8-2+9+9-8"; Context context = new Context(); Expression build = Context.build(str); System.out.println(str + " = " + build.interpreter(context)); } }