设计模式中属于行为模式的策略模式、状态模式、观察者模式、责任链模式、模板方法模式、迭代子模式、命令模式、备忘录模式、访问者模式、中介者模式、解释器模式
《设计模式之禅》笔记
策略模式
思想:定义一组算法,将每个算法封装起来,并且使他们之间可以互换。
/***
*
* 策略抽象
*/
public interface Strategy {
//策略模式的 算法则
public void doSomething();
}
/***
* 策略实现
*/
public class ConcreteStrategy1 implements Strategy {
public void doSomething() {
System.out.println("具体策略1的 算法则");
}
}
public class ConcreteStrategy2 implements Strategy {
public void doSomething() {
System.out.println("具体策略2的 算法则");
}
}
/***
* 上下文
*/
public class Context {
//抽象策略
private Strategy strategy = null;
//构造函数 置具体策略
public Context(Strategy _strategy){
this.strategy = _strategy;
}
public void doAnythinig(){
this.strategy.doSomething();
}
}
优点:
1.算法可以自由切换
2.避免使用多重条件判断
3.扩展性好
缺点:
1.复用性小策略策略增多的情况很恶心
2.所有策略类都要对外暴露
状态模式
思想:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
/**
* 抽象状态
*/
public abstract class State {
protected Context context;
public void setContext(Context _context){
this.context = _context;
}
//行为1
public abstract void handle1();
//行为2
public abstract void handle2();
}
public class ConcreteState1 extends State {
@Override
public void handle1() {
//本状态下必须处理的逻
}
@Override
public void handle2() {
// 置当前状态为stat2
super.context.setCurrentState(Context.STATE2);
//过渡到state2状态 由Context实现
super.context.handle2();
}
}
public class ConcreteState2 extends State {
@Override
public void handle1() {
//设置当前状态为state1
super.context.setCurrentState(Context.STATE1);
//过渡到state1状态 由Context实现
super.context.handle1();
}
@Override
public void handle2() {
//本状态下必须处理的逻
}
}
/**
* 客户端需要的接口 并且负责具体状态的切换。
*/
public class Context {
//定义状态
public final static State STATE1 = new ConcreteState1();
public final static State STATE2 = new ConcreteState2();
//当前状态
private State CurrentState;
// 得当前状态
public State getCurrentState() {
return CurrentState;
}
//设置当前状态
public void setCurrentState(State currentState) {
this.CurrentState = currentState;
//切换状态
this.CurrentState.setContext(this);
}
//行为委托
public void handle1(){
this.CurrentState.handle1();
}
public void handle2(){
this.CurrentState.handle2();
}
}
优点:
1.结构清晰
- 遵循设计原则
3.封装性好
缺点:子类多类膨胀太快
使用场景:行为改变状态场景,条件、分支判断语句替代者
策略模式和状态模式对比:
1.环境角色不同,两个设计模式都有一个context角色, 策略的context只是一个委托作用,状态模式的context里面有状态的记录和具体状态的协作共同完成状态的切换
2.解决问题的重点不同,策略模式解决内部算法改变对外部影响最小。状态模式解决内部状态改变引起的行为改变,出发点是状态对状态封装对行为暴露。
3.解决问题的方法不同,策略模式保证算法的自由切换,但是什么时候用什么算法控制不了,需要外部来选择。状态模式只对外暴露行为,算法的选择和状态的切换都是内部完成的。
4.应用场景不同,策略模式封装的是平行的一系列不易互换的算法。状态模式是必须有行为和状态的情况下才可以使用(可以理解算法=行为)
5.复杂度不同,策略模式比较简单
观察者模式
思想:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖与它的对象会收到通知更新。
/**
* 被观察者
*/
public abstract class Subject {
//定义一个观察者数组
private Vector obsVector = new Vector();
//增加一个观察者
public void addObserver(Observer o){
this.obsVector.add(o);
}
//删除一个观察者
public void delObserver(Observer o){
this.obsVector.remove(o);
}
//通知知所有观察者
public void notifyObservers(){
for(Observer o:this.obsVector){
o.update();
}
}
}
public class ConcreteSubject extends Subject {
public void doSomething(){
/*
* do something
*/
super.notifyObservers();
}
}
/**
* 观察者
*/
public interface Observer {
//更新方法
public void update();
}
public class ConcreteObserver implements Observer {
//实现更新方法
public void update() {
System.out.println("接收到信息处理 ");
}
}
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer obs= new ConcreteObserver();
subject.addObserver(obs);
subject.doSomething();
}
}
优点:
1.观察者和被观察者直接解耦
2.建立一套触发机制
缺点:效率问题多个观察者的时候
使用场景:
1.关联行为
2.事件多级触发场景
3.跨系统消息交换场景。mq
责任链模式
思想:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连城一条链,并沿着这条链传递该请求,直到有对象处理他为止。
/**
* 抽象处理者
*/
public abstract class Handler {
private Handler nextHandler;
//每个处理者必须对请求做出处理
public final Response handleMessage(Request request){
Response response = null;
//判断是否是自己的处理级别
if(this.getHandlerLevel().equals(request.getRequestLevel())){
response = this.echo(request);
}else{ //不属于自己的处理级别
//判断是否有下一个处理
if(this.nextHandler != null){
response = this.nextHandler.handleMessage(request);
}else{
//没有适当的处理者,业务自行处理
}
}
return response;
}
//设置下一个处理者
public void setNext(Handler _handler){
this.nextHandler = _handler;
}
//每个处理者有一个处理级别
protected abstract Level getHandlerLevel();
//每个处理者必须实现处理任务
protected abstract Response echo(Request request);
}
public class ConcreteHandler1 extends Handler {
protected Response echo(Request request) {
return null;
}
protected Level getHandlerLevel() {
return null;
}
}
public class ConcreteHandler2 extends Handler {
protected Response echo(Request request) {
return null;
}
protected Level getHandlerLevel() {
return null;
}
}
public class Level {
//定义一个请求和处理等级
}
public class Request {
//请求的等级
public Level getRequestLevel(){
return null;
}
}
public class Response {
//处理返回的数据
}
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setNext(handler2);
Response response = handler1.handlerMessage(new Request());
}
}
优点:
请求和处理分开,处理内容抽象隔离,提高系统灵活性
缺点:
性能问题,重头到位都要处理,调试不方便。
模板方法模式
思想:定义个操作算法框架,将一些步骤延迟到子类中。是的子类可以不改变一个算法的结构即可重新定义该算法的默写步骤。
代码略
优点:
1.封装不变部分,扩展可变部分
2.提取公共代码,便于维护
3.行为父类控制,子类实现
迭代子模式
思想:提供一种方法访问一个容器中的元素,但是有不暴露对象的内部细节。
代码例子,ArrayList 里面的迭代。
命令模式
思想:将一个请求封装成一个对象,从而让你使用不同的请求吧客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
/**
* 接收者
*/
public abstract class Receiver {
//抽象接收者,定义每个接收者必须完成的业务
public abstract void doSomething();
}
public class ConcreteReciver1 extends Receiver{
public void doSomething(){
}
}
public class ConcreteReciver2 extends Receiver{
public void doSomething(){
}
}
/**
* 命令
*/
public abstract class Command {
//每个命令类都必须有一个执行命令的方法
public abstract void execute();
}
public class ConcreteCommand1 extends Command {
private Receiver receiver;
public ConcreteCommand1(Receiver _receiver){
this.receiver = _receiver;
}
public void execute() {
this.receiver.doSomething();
}
}
public class ConcreteCommand2 extends Command {
private Receiver receiver;
public ConcreteCommand2(Receiver _receiver){
this.receiver = _receiver;
}
public void execute() {
this.receiver.doSomething();
}
}
/**
* 调用者
*/
public class Invoker {
private Command command;
public void setCommand(Command _command){
this.command = _command;
}
//执行命令
public void action(){
this.command.execute();
}
}
public class Client {
public static void main(String[] args) {
Invoker invoker = new Invoker();
//定义接收
Receiver receiver = new ConcreteReciver1();
//定义一个发送给接收者的命令
Command command = new ConcreteCommand1(receiver);
invoker.setCommand(command);
invoker.action();
}
}
优点:
1.类解耦,调用者和接受者之间没有任何关联,只需要调用command的execute方法就可以
2.可扩展性,命令非常容易扩展不影响调用者
3.和其他模式很好结合
缺点:类膨胀问题
备忘录模式
思想:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将对象恢复到原来状态。
/**
* 发起人
*/
public class Originator {
private String state = "";
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
/** 创建备忘录 */
public Memento createMemento(){
return new Memento(this.state);
}
/** 恢复 */
public void restoreMemento(Memento _memento){
this.setState(_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 Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
使用场景:
1.保存和恢复相关
2.提供一个回滚的操作
3.监控对象变化过程
访问者模式
思想:封装一些作用于某种数据结构中的各元素的操作,它可以不管变数据结构的前提下定义作用于这些元素新的操作。
/** 抽象元素: */
public abstract class Element {
//定义业务逻辑
public abstract void doSomething();
//允许谁来访问
public abstract void accept(IVisitor visitor);
}
public class ConcreteElement1 extends Element{
public void doSomething(){
}
public void accept(IVisitor visitor){
visitor.visit(this);
}
}
public class ConcreteElement2 extends Element{
public void doSomething(){
//业务处理
}
public void accept(IVisitor visitor){
visitor.visit(this);
}
}
/** 抽闲访问者 */
public interface IVisitor {
//可以访问哪些对象
public void visit(ConcreteElement1 el1);
public void visit(ConcreteElement2 el2);
}
public class Visitor implements IVisitor {
public void visit(ConcreteElement1 el1) {
el1.doSomething();
}
public void visit(ConcreteElement2 el2) {
el2.doSomething();
}
}
/** 结构对象 **/
public class ObjectStruture {
//对象生成器 一个工厂方法模式模拟
public static Element createElement(){
Random rand = new Random();
if(rand.nextInt(100) > 50){
return new ConcreteElement1();
}else{
return new ConcreteElement2();
}
}
}
public class Client {
public static void main(String[] args) {
for(int i=0;i<10;i++){
Element el = ObjectStruture.createElement();
el.accept(new Visitor());
}
}
}
优点:
1.符合单一职责原则,访问则和元素抽象开,每个人都干自己的事情
2.优秀的扩展
3.灵活性高
缺点:
1.细节对访问者公开
2.具体的元素变化比较困难
3.违背了依赖倒置原则
中介者模式
思想:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
/** 抽象中介者 */
public abstract class Mediator {
//定义同事类
protected ConcreteColleague1 c1;
protected ConcreteColleague2 c2;
// getter/setter方法把同事类注入进来
public ConcreteColleague1 getC1() {
return c1;
}
public void setC1(ConcreteColleague1 c1) {
this.c1 = c1;
}
public ConcreteColleague2 getC2() {
return c2;
}
public void setC2(ConcreteColleague2 c2) {
this.c2 = c2;
}
//中介模式的业务逻
public abstract void doSomething1();
public abstract void doSomething2();
}
public class ConcreteMediator extends Mediator {
@Override
public void doSomething1() {
super.c1.selfMethod1();
super.c2.selfMethod2();
}
public void doSomething2() {
super.c1.selfMethod1();
super.c2.selfMethod2();
}
}
/** 抽象业务类 */
public abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator _mediator){
this.mediator = _mediator;
}
}
public class ConcreteColleague1 extends Colleague {
public ConcreteColleague1(Mediator _mediator){
super(_mediator);
}
public void selfMethod1(){
}
public void depMethod1(){
super.mediator.doSomething1();
}
}
public class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator _mediator){
super(_mediator);
}
public void selfMethod2(){
}
public void depMethod2(){
super.mediator.doSomething2();
}
}
优点:
1.减少类之间的依赖
缺点:
1.中介者膨胀类关系复杂
使用场景:一个对象要与多个对象发生关系时
解释器模式
思想:给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示解释语言中的句子。
/** 抽象表达式 */
public abstract class Expression {
// 解析
public abstract Object interpreter(Context ctx);
}
/** 终结符表达式 */
public class TerminalExpression extends Expression {
public Object interpreter(Context ctx) {
return null;
}
}
/** 普通表达式 */
public class NonterminalExpression extends Expression {
//每个非终结符表对其它表达式的依赖
public NonterminalExpression(Expression... expression){
}
public Object interpreter(Context ctx) {
// 行文法处理
return null;
}
}
public class Client {
public static void main(String[] args) {
Context ctx = new Context();
// 常定一个语法法容器通常常为ListArray、LinkedList、Stack等类型
Stack stack = null;
for(;;){
//进行语法判断并产生递归调用
}
Expression exp = stack.pop();
exp.interpreter(ctx);
}
}