最近加班是真的不少,没法腾出大块时间来学习。设计模式又不想只更到一半半途而废,想了又想,决定精简,保证你们一看就懂(看完就忘...)。设计模式分建立型模式,结构型模式和行为型模式。到目前为止,建立型模式已经讲完,对于剩下的模式,会分红这两大块统一讲解。算法
行为型模式主要关注的点事类的动做,各个类之间相互的做用,将职责划分清楚,使咱们的代码更加的清晰。数据库
定义一组算法,将每一个算法都封装起来,而且使他们之间能够互换。
策略模式是一个出现频率很高,但又很简单的模式。下面的场景是咱们要出去旅游,可是能够选择出去旅游的交通方式,好比坐飞机,坐火车或者步行。废话再也不多说,直接上码:
public interface Strategy { void travel(); }
public class Walk implements Strategy { @Override public void travel() { System.out.println("步行去旅行"); } }
public class Train implements Strategy { @Override public void travel() { System.out.println("坐火车去旅行"); } }
public class Airplane implements Strategy { @Override public void travel() { System.out.println("坐着飞机去旅行"); } }
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void execute(){ strategy.travel(); } }
public class Client { public static void main(String[] args) { Context context = new Context(new Airplane()); context.execute(); } } console: 坐着飞机去旅行
策略模式的优势很是明显,在现有的系统中增长一个策略太容易,只要实现接口就能够了,其余都不用修改,相似于一个能够反复拆卸的插件,符合ocp原则。其缺点就是每一个策略都是一个类,复用性很小,复杂的业务场景容易发生类数量爆炸,而且策略模式和迪米特法则是违背的,咱们看下上面的clent场景类(至关于项目中的高层调用模块),我只是想使用一个策略,凭什么就要了解这个策略呢?那要封装类就没有意义了,这是策略模式的一个大缺点,因此策略模式不多单独出现,大多结合其余模式来弥补这个缺陷,如工厂方法或者代理模式。segmentfault
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则全部依赖于它的对象都会获得通知并被自动更新
策略模式也叫发布订阅模式,其中最主要额角色名称就是subject被观察者和observer观察者。接下来会模拟一个场景,学校做为被观察者发布放假的消息,家长和学生做为观察者实现本身的逻辑:设计模式
/** * 主题(被观察者)须要实现的职责,就是能够动态的增长删除观察者。 * 根据主题的状态通知全部的观察者Observer */ public abstract class Subject { private Vector<Observer> observerList = new Vector<>(); private int status; public void addObserver(Observer observer){ observerList.add(observer); } public void delObserver(Observer observer){ observerList.remove(observer); } public void notifyAllObserver(){ observerList.forEach(observer -> { observer.update(); }); } }
public class SchoolSubject extends Subject { //学校宣布放七天假期 public void haveSevenDaysHoliday(){ System.out.println("学校:从今天开始放假,全部学生七天后返校"); super.notifyAllObserver(); } }
public interface Observer { //观察者,被通知了实现其本身的逻辑 void update() ; }
public class Parent implements Observer { @Override public void update() { System.out.println("家长:这倒霉孩子怎么又放假了,坚定不能让他玩王者荣耀...."); } }
public class Student implements Observer { @Override public void update() { System.out.println("学生:哇哈哈,终于有时间打王者荣耀喽"); } }
public class Client { public static void main(String[] args) { SchoolSubject subject = new SchoolSubject(); Student student = new Student(); Parent parent = new Parent(); subject.addObserver(student); subject.addObserver(parent); subject.haveSevenDaysHoliday(); } } console: 学校:从今天开始放假,全部学生七天后返校 学生:哇哈哈,终于有时间打王者荣耀喽 家长:这倒霉孩子怎么又放假了,坚定不能让他玩王者荣耀....
虽然说观察者和被观察者是耦合在一块儿的,可是不论是扩展增长观察者仍是被观察者都很是容易。而且根据单一职责原则,每一个类的职责都是惟一,须要一套机制将类串联起来造成一个真实的场景,就好比学校公布放假,孩子想着玩游戏,家长为了孩子的成绩禁止孩子玩游戏,而后由于学校放假我就不玩了(小学生,你懂得),这样就造成了一个触发机制。其缺点就是执行效率低下,需异步执行。从原理上看,咱们经常使用的mq就是观察者模式的升级版。异步
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链咱们很容易想到链表结构,实际上责任链就是一种基于链表的处理方式。当一个请求过来,调用链表的头结点,处理以后再日后流转。
有这么一个场景:路飞饿了打开美团准备订外卖。选中吃的后,进行下单,首先校验是否在营业时间内,而后校验是否在配送范围内,而后校验是否有货等等,设定责任链都经过后,路飞才能订到饭。ide
//链表内结点的基类 public abstract class RuleHandler { protected RuleHandler successor; public abstract void echo(Context context); public void setSuccessor(RuleHandler successor) { this.successor = successor; } public RuleHandler getSuccessor() { return successor; } }
//判断营业时间 public class TimeHandler extends RuleHandler { @Override public void echo(Context context) { //营业时间判断 if (context.isTimeInRange()){ if (this.getSuccessor()!=null){ this.getSuccessor().echo(context); } }else { throw new RuntimeException("不在营业时间内"); } } }
//判断是否在配送范围内 public class AreaHanler extends RuleHandler { @Override public void echo(Context context) { if (context.isAreaInRange()){ if (this.getSuccessor()!=null){ this.getSuccessor().echo(context); } }else { throw new RuntimeException("不在配送范围内"); } } }
//判断库存 public class StockHandler extends RuleHandler { @Override public void echo(Context context) { if (context.hasStock()){ if (this.getSuccessor()!=null){ this.getSuccessor().echo(context); } }else { throw new RuntimeException("挑选的商品已经卖完"); } } }
客户端调用逻辑:性能
public class Client { public static void main(String[] args) { RuleHandler timeHandler = new TimeHandler(); RuleHandler areaHandler = new AreaHanler(); RuleHandler stockHandler = new StockHandler(); timeHandler.setSuccessor(areaHandler); areaHandler.setSuccessor(stockHandler); timeHandler.echo(new Context()); } }
代码很是简单,责任链模式的重点是在链上,由一条链去处理请求并返回相应的结果。它很是显著的优势就是将请求和处理分开,二者解耦,提升系统的灵活性。缺点就是链表遍历必须从链头到链尾,存在性能问题。采用了相似递归调用的方式,增大了读懂逻辑的难度学习
在以前的博客里已经长篇大论过,故直接拿过来。
模板方法测试
当一个对象内在状态改变时容许其改变行为,这个对象看起来像改变了其类。
状态模式的核心是封装,经过状态的变动引发行为的变动。如今你们来思考一下,电脑有三种状态,分别为关机,已启动。this
//表明环境,也就是状态的主体 public class Context { //全部的电脑状态 public final static OpenState OPEN = new OpenState(); public final static CloseState CLOSE = new CloseState(); //电脑当前的状态 private ComputerState currentState; public ComputerState getCurrentState() { return currentState; } public void setCurrentState(ComputerState currentState) { this.currentState = currentState; this.currentState.setContext(this); } public void openMachine() { this.currentState.openMachine(); } public void closeMachine() { this.currentState.closeMachine(); } }
//状态基类,真实的电脑逻辑封装在了状态中 public abstract class ComputerState { protected Context context; public void setContext(Context context) { this.context = context; } public abstract void openMachine(); public abstract void closeMachine(); }
public class OpenState extends ComputerState{ @Override public void openMachine() { System.out.println("电脑开机..."); } @Override public void closeMachine() { super.context.setCurrentState(Context.CLOSE); super.context.getCurrentState().closeMachine(); } }
public class CloseState extends ComputerState { @Override public void openMachine() { super.context.setCurrentState(Context.OPEN); super.context.getCurrentState().openMachine(); } @Override public void closeMachine() { System.out.println("电脑关机..."); } }
客户端测试类:
public class Client { public static void main(String[] args) { Context context = new Context(); context.setCurrentState(Context.OPEN); context.openMachine(); context.closeMachine(); } }
状态模式的优势有结构清晰,避免了各类条件的判断,省掉了swtich...case,if...else语句的使用,提高了代码的可读性。遵循了单一职责原则和开闭原则,每一个状态都是一个子类,增长状态只需增长一个状态子类,修改状态,修改对应的子类就能够了。封装性很是好,客户端不需知道内部状态的转换以及相应的逻辑.其缺点就是状态子类会太多,而且咱们能够将状态存储到数据库中,而后根据状态执行相应的操做,这也是一种不错的实现方式,具体如何使用看你们我的喜爱了。
本章的行为型模式总结了策略模式、观察者模式、责任链模式、模板方法模式和状态模式,其实不只于此,还有备忘录模式和命令模式等,但因其使用场景有限,就不作一一探讨了,留给读者本身学习~.~