Leetcode-设计模式-行为型模式
Posted 钢铁-程序猿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode-设计模式-行为型模式相关的知识,希望对你有一定的参考价值。
文章目录
- 行为型模式
- 一、责任链模式(责任链主要用于处理 职责相同,程度不同的类)
- 二、命令模式(实现同一个接口,通过多态的方式调用方法,实现不同的命令功能)
- 三、解释器模式(若问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题)
- 四、迭代器模式(提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节)
- 五、中介者模式(用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互)
- 六、备忘录模式(在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态)
- 七、观察者模式(定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新)
- 八、状态模式(对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。)
- 九、策略模式(定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。)
- 十、模板方法模式(模板方法模式就是一个关于继承的设计模式,主要解决一些方法通用,却在每一个子类都重新写了这一方法)
- 十一、访问者模式
- 总结
行为型模式
一、责任链模式(责任链主要用于处理 职责相同,程度不同的类)
责任链模式的优点:
- 降低对象之间的耦合
- 扩展性强,符合开闭原则
- 灵活性强
- 简化对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用
缺点:
- 如果责任链过长,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 不能保证每个请求一定被处理,该请求可能一直传到链的末端都得不到处理。
例子
新建一个程序员抽象类:
public abstract class Programmer
protected Programmer next;
public void setNext(Programmer next)
this.next = next;
abstract void handle(Bug bug);
在这个抽象类中:
- next 对象表示如果自己解决不了,需要将责任传递给的下一个人;
- handle 方法表示自己处理此 bug 的逻辑,在这里判断是自己解决或者继续传递。
新建菜鸟程序员类:
public class NewbieProgrammer extends Programmer
@Override
public void handle(Bug bug)
if (bug.value > 0 && bug.value <= 20)
solve(bug);
else if (next != null)
next.handle(bug);
private void solve(Bug bug)
System.out.println("菜鸟程序员解决了一个难度为 " + bug.value + " 的 bug");
新建普通程序员类:
public class NormalProgrammer extends Programmer
@Override
public void handle(Bug bug)
if (bug.value > 20 && bug.value <= 50)
solve(bug);
else if (next != null)
next.handle(bug);
private void solve(Bug bug)
System.out.println("普通程序员解决了一个难度为 " + bug.value + " 的 bug");
新建优秀程序员类:
public class GoodProgrammer extends Programmer
@Override
public void handle(Bug bug)
if (bug.value > 50 && bug.value <= 100)
solve(bug);
else if (next != null)
next.handle(bug);
private void solve(Bug bug)
System.out.println("优秀程序员解决了一个难度为 " + bug.value + " 的 bug");
客户端测试:
import org.junit.Test;
public class Client4
@Test
public void test()
NewbieProgrammer newbie = new NewbieProgrammer();
NormalProgrammer normal = new NormalProgrammer();
GoodProgrammer good = new GoodProgrammer();
Bug easy = new Bug(20);
Bug middle = new Bug(50);
Bug hard = new Bug(100);
// 组成责任链
newbie.setNext(normal);
normal.setNext(good);
// 从菜鸟程序员开始,沿着责任链传递
newbie.handle(easy);
newbie.handle(middle);
newbie.handle(hard);
二、命令模式(实现同一个接口,通过多态的方式调用方法,实现不同的命令功能)
请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
命令模式的主要优点如下:
- 降低系统的耦合度。将 “行为请求者” 和 ”行为实现者“ 解耦。
- 扩展性强。增加或删除命令非常方便,并且不会影响其他类。
- 封装 “方法调用”,方便实现 Undo 和 Redo 操作。
- 灵活性强,可以实现宏命令。
它的主要缺点是:
- 会产生大量命令类。增加了系统的复杂性。
例子
创建一个命令接口。
Order.java
public interface Order
void execute();
步骤 2
创建一个请求类。
Stock.java
public class Stock
private String name = "ABC";
private int quantity = 10;
public void buy()
System.out.println("Stock [ Name: "+name+",
Quantity: " + quantity +" ] bought");
public void sell()
System.out.println("Stock [ Name: "+name+",
Quantity: " + quantity +" ] sold");
步骤 3
创建实现了 Order 接口的实体类。
BuyStock.java
public class BuyStock implements Order
private Stock abcStock;
public BuyStock(Stock abcStock)
this.abcStock = abcStock;
public void execute()
abcStock.buy();
SellStock.java
public class SellStock implements Order
private Stock abcStock;
public SellStock(Stock abcStock)
this.abcStock = abcStock;
public void execute()
abcStock.sell();
步骤 4
创建命令调用类。
Broker.java
import java.util.ArrayList;
import java.util.List;
public class Broker
private List<Order> orderList = new ArrayList<Order>();
public void takeOrder(Order order)
orderList.add(order);
public void placeOrders()
for (Order order : orderList)
order.execute();
orderList.clear();
步骤 5
使用 Broker 类来接受并执行命令。
CommandPatternDemo.java
public class CommandPatternDemo
public static void main(String[] args)
Stock abcStock = new Stock();
BuyStock buyStockOrder = new BuyStock(abcStock);
SellStock sellStockOrder = new SellStock(abcStock);
Broker broker = new Broker();
broker.takeOrder(buyStockOrder);
broker.takeOrder(sellStockOrder);
broker.placeOrders();
步骤 6
执行程序,输出结果:
Stock [ Name: ABC, Quantity: 10 ] bought
Stock [ Name: ABC, Quantity: 10 ] sold
我们期待能有一种设计,让遥控器不需要知道家居的接口。它只需要负责监听用户按下开关,再根据开关状态发出正确的命令,对应的家居在收到命令后做出响应。就可以达到将 “行为请求者” 和 ”行为实
三、解释器模式(若问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题)
面向过程编程会有耦合度高,不易扩展等缺点
如何解决:构建语法树,定义终结符与非终结符。
在解释器模式中,我们将不可拆分的最小单元称之为终结表达式,可以被拆分的表达式称之为非终结表达式。
解释器模式中常用到递归,递归解析语句。
使用场景:
- 1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
- 2、一些重复出现的问题可以用一种简单的语言来进行表达。
- 3、一个简单语法需要解释的场景。
例子
步骤 1
创建一个表达式接口。
public interface Expression
public boolean interpret(String context);
步骤 2
创建实现了上述接口的实体类。
TerminalExpression.java
public class TerminalExpression implements Expression
private String data;
public TerminalExpression(String data)
this.data = data;
@Override
public boolean interpret(String context)
if(context.contains(data))
return true;
return false;
OrExpression.java
public class OrExpression implements Expression
private Expression expr1 = null;
private Expression expr2 = null;
public OrExpression(Expression expr1, Expression expr2)
this.expr1 = expr1;
this.expr2 = expr2;
@Override
public boolean interpret(String context)
return expr1.interpret(context) || expr2.interpret(context);
AndExpression.java
public class AndExpression implements Expression
private Expression expr1 = null;
private Expression expr2 = null;
public AndExpression(Expression expr1, Expression expr2)
this.expr1 = expr1;
this.expr2 = expr2;
@Override
public boolean interpret(String context)
return expr1.interpret(context) && expr2.interpret(context);
步骤 3
InterpreterPatternDemo 使用 Expression 类来创建规则,并解析它们。
InterpreterPatternDemo.java
public class InterpreterPatternDemo
//规则:Robert 和 John 是男性
public static Expression getMaleExpression()
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
return new OrExpression(robert, john);
//规则:Julie 是一个已婚的女性
public static Expression getMarriedWomanExpression()
Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
public static void main(String[] args)
Expression isMale = getMaleExpression();
Expression isMarriedWoman = getMarriedWomanExpression();
System.out.println("John is male? " + isMale.interpret("John"));
System.out.println("Julie is a married women? "
+ isMarriedWoman.interpret("Married Julie"));
步骤 4
执行程序,输出结果:
John is male? true
Julie is a married women? true
四、迭代器模式(提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节)
五、中介者模式(用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互)
何时使用:多个类相互耦合,形成了网状结构。
如何解决:将上述网状结构分离为星型结构。
例子
创建中介类。
ChatRoom.java
import java.util.Date;
public class ChatRoom
public static void showMessage(User user, String message)
System.out.println(new Date().toString()
+ " [" + user.getName() +"] : " + message);
步骤 2
创建 user 类。
User.java
public class User
private String name;
public String getName()
return name;
public void setName(String name)
this.name = name;
public User(String name)
this.name = name;
public void sendMessage(String message)
ChatRoom.showMessage(this,message);
步骤 3
使用 User 对象来显示他们之间的通信。
MediatorPatternDemo.java
public class MediatorPatternDemo
public static void main(String[] args)
User robert = new User("Robert");
User john = new User("John");
robert.sendMessage("Hi! John!");
john.sendMessage("Hello! Robert!");
步骤 4
执行程序,输出结果:
Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!
六、备忘录模式(在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态)
主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
如何解决:通过一个备忘录类专门存储对象状态。
例子
备忘录模式使用三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。
创建 Memento 类。
Memento.java
public class Memento
private String state;
public Memento(String state)
this.state = state;
public String getState()
return state;
步骤 2
创建 Originator 类。
Originator.java
public class Originator
private String state;
public void setState(String state)
this.state = state;
public String getState()
return state;
public Memento saveStateToMemento()
return new Memento(state);
public void getStateFromMemento(Memento Memento)
state = Memento.getState();
步骤 3
创建 CareTaker 类。
CareTaker.java
import java.util.ArrayList;
import java.util.List;
public class CareTaker
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento state)
mementoList.add(state);
public Memento get(int index)
return mementoList.get(index);
步骤 4
使用 CareTaker 和 Originator 对象。
MementoPatternDemo.java
public class MementoPatternDemo
public static void main(以上是关于Leetcode-设计模式-行为型模式的主要内容,如果未能解决你的问题,请参考以下文章