定义

将对象组合成树型结构,以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

类型

结构类模式

类图

Composite Pattern

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public abstract class Component {
public void doSomething(){
//业务逻辑
}
}

public class Composite extends Component {
private ArrayList<Component> componentArrayList = new ArrayList<Component>();

public void add(Component component){
this.componentArrayList.add(component);
}

public void remove(Component component){
this.componentArrayList.remove(component);
}

public ArrayList<Component> getChildren() {
return this.componentArrayList;
}
}

public class Leaf extends Component {
public void doSomething() {

}
}

public class Client {
public static void main(String[] args){
Composite root = new Composite();
root.doSomething();

Composite branch = new Composite();
Leaf leaf = new Leaf();
root add(leaf);
}
}

优点

  • 高层模块调用简单
  • 节点自由增加

缺点

树叶和树枝使用时直接使用了实现类,在面向接口编程上是很不恰当的,与依赖倒置原则冲突。

## 使用场景

  • 维护和展示部分——整体关系的场景,比如树形菜单,文件和文件夹管理
  • 从一个整体中能够独立出部分模块或功能的场景

评论和共享

定义

将抽象和实现解耦,使得两者可以独立的变化

类型

结构类模式

类图

Bridge Pattern

角色

  • Abstraction——抽象化角色
  • Implementor——实现化角色
  • RefinedAbstraction——修正抽象化角色
  • ConcreteImplementor——具体实现化角色

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public interface Implementor {
public void doSomething();
public void doAnything();
}

public class ConcreteImplementor1 implements Implementor {
public void doSomething(){
//业务逻辑处理
}
public void doAnything() {
//业务逻辑处理
}
}
//ConcreteImplementor2 省略

public abstract class Abstraction {
private Implementor imp;
public Abstraction(Implementor _imp){
this.imp = _imp;
}
public void request() {
this.imp.doSomething();
}
public Implementor getImp(){
return imp;
}
}

public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor _imp){
super(_imp);
}
@Override
public void request(){
super.request();
super.getImp().doAnything();
}
}

public class Client {
public static void main(String[] args) {
Implementor imp = new ConcreteImplementor1();
Abstraction abs = new RefinedAbstraction(imp);
abs.request();
}
}

优点

  • 抽象和实现分离
  • 优秀的拓展能力
  • 实现细节对客户透明

使用场景

  • 不希望或不适用使用继承的场景
  • 接口或抽象类不稳定的场景
  • 重用性要求较高的场景

评论和共享

定义

为其他对象提供一种代理以控制对这个对象的访问

类型

结构类模式

类图

Proxy Pattern

角色

  • Subject——抽象主题角色
  • RealSubject——具体主题角色
  • Proxy——代理主题角色

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public interface Subject {
public void request();
}

public class RealSubject implements Subject {
public void request(){
//业务逻辑处理
}
}

public class Proxy implements Subject {
private Subject subject = null;

public Proxy() {
this.subject = new Proxy();
}

public Proxy(Object...object){

}

public void request() {
this.before();
this.subject.request();
this.after();
}

private void before() {

}

private void after() {

}
}

优点

  • 职责清晰
  • 高拓展性
  • 智能化

评论和共享

定义

讲一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作

类型

结构类模式

类图

Adapter Pattern

要素

  • Target——目标角色
  • Adapter——源角色
  • Adapter——适配器角色

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public interface Target {
public void request();
}

public class ConcreteTarget implements Target {
public void request() {
System.out.println("if you need any help, pls call me!");
}
}

public class Adaptee {
public void doSomething() {
System.out.println("I'm kind of busy, leave me alone, pls!")
}
}

public class Adapter extends Adaptee implements Target {
public void request() {
super.doSomething();
}
}

public class Client {
public static void main(String[] args) {
Target target = new ConcreteTarget();
target.request();

Target target2 = new Adapter();
target2.request();
}
}

优点

  • 可以让两个没有任何关系的类在一起运行。
  • 增加了类的透明性
  • 提高了类的复用度
  • 灵活性非常好

使用场景

在详细设计阶段不用考虑,而是解决正在复议的项目的问题

评论和共享

定义

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

类型

创建类模式

类图

State Pattern

要素

  • State——抽象状态角色

    接口抽象类,负责对象状态定义,并且封装环境角色以实现状态转换。

  • ConcreteState——具体状态角色

    每一个具体状态必须完成两个职责: 本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态

  • Context——环境角色

    定义客户端需要的接口,并且负责具体状态的切换。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public abstract class State {
protected Context context;

public void setContext(Context _context){
this.context = _context;
}

public abstract void handle1();

public abstract void handle2();
}

public class ConcreteState1 extends State {
@Override
public void handle1(){
super.context.setCurrectState(Context.STATE2);
super.context.handle2();
}
@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();
}
}

public class Client {
public static void main(String[] args){
Context context = new Context();
context.setCurrentState(new ConcreteState1);

context.handle1();
context.handle2();
}
}

优点

  • 结构清晰

    避免许多switch…case

  • 遵循设计原则

    很好地体现了开闭原则和单一职责原则

  • 封装性非常好

缺点

子类会太多,可以解决,比如在数据库中建立一个状态表,然后根据状态执行相应的操作。

使用场景

  • 行为随状态改变而改变的场景
  • 条件,分支判断语句的代替者

评论和共享

定义

给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。

类型

行为类模式

类图

Interpreter Pattern

结构

  • 抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。
  • 终结符表达式:实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一半是文法中的运算单元,比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
  • 非终结符表达式:文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
  • 环境角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Context {}  
abstract class Expression {
public abstract Object interpreter(Context ctx);
}
class TerminalExpression extends Expression {
public Object interpreter(Context ctx){
return null;
}
}
class NonterminalExpression extends Expression {
public NonterminalExpression(Expression...expressions){

}
public Object interpreter(Context ctx){
return null;
}
}
public class Client {
public static void main(String[] args){
String expression = "";
char[] charArray = expression.toCharArray();
Context ctx = new Context();
Stack<Expression> stack = new Stack<Expression>();
for(int i=0;i<charArray.length;i++){
//进行语法判断,递归调用
}
Expression exp = stack.pop();
exp.interpreter(ctx);
}
}

优点

解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。

缺点

解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。同时,由于采用递归调用方法,每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,必须通过递归方式,无论是面向对象的语言还是面向过程的语言,递归都是一个不推荐的方式。由于使用了大量的循环和递归,效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。

适用场景

在以下情况下可以使用解释器模式:

  • 有一个简单的语法规则,比如一个sql语句,如果我们需要根据sql语句进行rm转换,就可以使用解释器模式来对语句进行解释。
  • 一些重复发生的问题,比如加减乘除四则运算,但是公式每次都不同,有时是a+b-cd,有时是ab+c-d,等等等等个,公式千变万化,但是都是由加减乘除四个非终结符来连接的,这时我们就可以使用解释器模式。

注意事项

解释器模式真的是一个比较少用的模式,因为对它的维护实在是太麻烦了,想象一下,一坨一坨的非终结符解释器,假如不是事先对文法的规则了如指掌,或者是文法特别简单,则很难读懂它的逻辑。解释器模式在实际的系统开发中使用的很少,因为他会引起效率、性能以及维护等问题。

评论和共享

定义

提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。

类型

行为类模式

类图

Iterator Pattern

迭代器模式的结构

  • 抽象容器:一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
  • 具体容器:就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。
  • 抽象迭代器:定义遍历元素所需要的方法,一般来说会有这么三个方法:取得第一个元素的方法first(),取得下一个元素的方法next(),判断是否遍历结束的方法isDone()(或者叫hasNext()),移出当前对象的方法remove(),
  • 迭代器实现:实现迭代器接口中定义的方法,完成集合的迭代。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
interface Iterator {  
public Object next();
public boolean hasNext();
}
class ConcreteIterator implements Iterator{
private List list = new ArrayList();
private int cursor =0;
public ConcreteIterator(List list){
this.list = list;
}
public boolean hasNext() {
if(cursor==list.size()){
return false;
}
return true;
}
public Object next() {
Object obj = null;
if(this.hasNext()){
obj = this.list.get(cursor++);
}
return obj;
}
}
interface Aggregate {
public void add(Object obj);
public void remove(Object obj);
public Iterator iterator();
}
class ConcreteAggregate implements Aggregate {
private List list = new ArrayList();
public void add(Object obj) {
list.add(obj);
}

public Iterator iterator() {
return new ConcreteIterator(list);
}

public void remove(Object obj) {
list.remove(obj);
}
}
public class Client {
public static void main(String[] args){
Aggregate ag = new ConcreteAggregate();
ag.add("小明");
ag.add("小红");
ag.add("小刚");
Iterator it = ag.iterator();
while(it.hasNext()){
String str = (String)it.next();
System.out.println(str);
}
}
}

优点

  • 简化了遍历方式,对于对象集合的遍历,还是比较麻烦的,对于数组或者有序列表,我们尚可以通过游标来取得,但用户需要在对集合了解很清楚的前提下,自行遍历对象,但是对于hash表来说,用户遍历起来就比较麻烦了。而引入了迭代器方法后,用户用起来就简单的多了。
  • 可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
  • 封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。

缺点

对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。

适用场景

  • 迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。
  • 但是,由于容器与迭代器的关系太密切了,所以大多数语言在实现容器的时候都给提供了迭代器,并且这些语言提供的容器和迭代器在绝大多数情况下就可以满足我们的需要,所以现在需要我们自己去实践迭代器模式的场景还是比较少见的,我们只需要使用语言中已有的容器和迭代器就可以了。

评论和共享

定义

定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。

类型

行为类模式

类图

Strategy Pattern

策略模式的结构

  • 封装类:也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
  • 抽象策略:通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
  • 具体策略:具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
interface IStrategy {  
public void doSomething();
}
class ConcreteStrategy1 implements IStrategy {
public void doSomething() {
System.out.println("具体策略1");
}
}
class ConcreteStrategy2 implements IStrategy {
public void doSomething() {
System.out.println("具体策略2");
}
}
class Context {
private IStrategy strategy;

public Context(IStrategy strategy){
this.strategy = strategy;
}

public void execute(){
strategy.doSomething();
}
}

public class Client {
public static void main(String[] args){
Context context;
System.out.println("-----执行策略1-----");
context = new Context(new ConcreteStrategy1());
context.execute();

System.out.println("-----执行策略2-----");
context = new Context(new ConcreteStrategy2());
context.execute();
}
}

优点

  • 策略类之间可以自由切换,由于策略类实现自同一个抽象,所以他们之间可以自由切换。
    易于扩展,增加一个新的策略对策略模式来说非常容易,基本上可以在不改变原有代码的基础上进行扩展。
  • 避免使用多重条件,如果不使用策略模式,对于所有的算法,必须使用条件语句进行连接,通过条件判断来决定使用哪一种算法,在上一篇文章中我们已经提到,使用多重条件判断是非常不容易维护的。

缺点

  • 维护各个策略类会给开发带来额外开销,可能大家在这方面都有经验:一般来说,策略类的数量超过5个,就比较令人头疼了。
  • 违反迪米特法则:必须对客户端(调用者)暴露所有的策略类,因为使用哪种策略是由客户端来决定的,因此,客户端应该知道有什么策略,并且了解各种策略之间的区别,否则,后果很严重。例如,有一个排序算法的策略模式,提供了快速排序、冒泡排序、选择排序这三种算法,客户端在使用这些算法之前,是不是先要明白这三种算法的适用情况?再比如,客户端要使用一个容器,有链表实现的,也有数组实现的,客户端是不是也要明白链表和数组有什么区别?就这一点来说是有悖于迪米特法则的。

适用场景

做面向对象设计的,对策略模式一定很熟悉,因为它实质上就是面向对象中的继承和多态,在看完策略模式的通用代码后,我想,即使之前从来没有听说过策略模式,在开发过程中也一定使用过它吧?至少在在以下两种情况下,大家可以考虑使用策略模式,

  • 几个类的主要逻辑相同,只在部分逻辑的算法和行为上稍有区别的情况。
  • 有几种相似的行为,或者说算法,客户端需要动态地决定使用哪一种,那么可以使用策略模式,将这些算法封装起来供客户端调用。

评论和共享

定义

使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

类型

行为类模式

类图

Chain Of Responsibility

## 责任连模式的结构

  • 抽象处理类:抽象处理类中主要包含一个指向下一处理类的成员变量nextHandler和一个处理请求的方法handRequest,handRequest方法的主要主要思想是,如果满足处理的条件,则有本处理类来进行处理,否则由nextHandler来处理。
  • 具体处理类:具体处理类主要是对具体的处理逻辑和处理的适用条件进行实现。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
class Level {  
private int level = 0;
public Level(int level){
this.level = level;
};

public boolean above(Level level){
if(this.level >= level.level){
return true;
}
return false;
}
}

class Request {
Level level;
public Request(Level level){
this.level = level;
}

public Level getLevel(){
return level;
}
}

class Response {

}

abstract class Handler {
private Handler nextHandler;
public final Response handleRequest(Request request){
Response response = null;

if(this.getHandlerLevel().above(request.getLevel())){
response = this.response(request);
}else{
if(this.nextHandler != null){
this.nextHandler.handleRequest(request);
}else{
System.out.println("-----没有合适的处理器-----");
}
}
return response;
}
public void setNextHandler(Handler handler){
this.nextHandler = handler;
}
protected abstract Level getHandlerLevel();
public abstract Response response(Request request);
}

class ConcreteHandler1 extends Handler {
protected Level getHandlerLevel() {
return new Level(1);
}
public Response response(Request request) {
System.out.println("-----请求由处理器1进行处理-----");
return null;
}
}

class ConcreteHandler2 extends Handler {
protected Level getHandlerLevel() {
return new Level(3);
}
public Response response(Request request) {
System.out.println("-----请求由处理器2进行处理-----");
return null;
}
}

class ConcreteHandler3 extends Handler {
protected Level getHandlerLevel() {
return new Level(5);
}
public Response response(Request request) {
System.out.println("-----请求由处理器3进行处理-----");
return null;
}
}

public class Client {
public static void main(String[] args){
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();

handler1.setNextHandler(handler2);
handler2.setNextHandler(handler3);

Response response = handler1.handleRequest(new Request(new Level(4)));
}
}

优点

责任链模式与if…else…相比,他的耦合性要低一些,因为它把条件判定都分散到了各个处理类中,并且这些处理类的优先处理顺序可以随意设定

缺点

在找到正确的处理类之前,所有的判定条件都要被执行一遍,当责任链比较长时,性能问题比较严重。

责任链模式的适用场景

就像开始的例子那样,假如使用if…else…语句来组织一个责任链时感到力不从心,代码看上去很糟糕时,就可以使用责任链模式来进行重构。

总结

责任链模式其实就是一个灵活版的if…else…语句,它就是将这些判定条件的语句放到了各个处理类中,这样做的优点是比较灵活了,但同样也带来了风险,比如设置处理类前后关系时,一定要特别仔细,搞对处理类前后逻辑的条件判断关系,并且注意不要在链中出现循环引用的问题。

责任连模式常常会和模板方法一起使用

评论和共享

定义

将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

类型

行为类模式

类图

Command Pattern

命令模式的结构

  • Command类:是一个抽象类,类中对需要执行的命令进行声明,一般来说要对外公布一个execute方法用来执行命令。
  • ConcreteCommand类:Command类的实现类,对抽象类中声明的方法进行实现。
  • Client类:最终的客户端调用类。
  • Invoker类:调用者,负责调用命令。
  • Receiver类:接收者,负责接收命令并且执行命令。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Invoker {  
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void action(){
this.command.execute();
}
}

abstract class Command {
public abstract void execute();
}

class ConcreteCommand extends Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
public void execute() {
this.receiver.doSomething();
}
}

class Receiver {
public void doSomething(){
System.out.println("接受者-业务逻辑处理");
}
}

public class Client {
public static void main(String[] args){
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
//客户端直接执行具体命令方式(此方式与类图相符)
command.execute();

//客户端通过调用者来执行命令
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.action();
}
}

命令模式的优缺点

首先,命令模式的封装性很好:每个命令都被封装起来,对于客户端来说,需要什么功能就去调用相应的命令,而无需知道命令具体是怎么执行的。比如有一组文件操作的命令:新建文件、复制文件、删除文件。如果把这三个操作都封装成一个命令类,客户端只需要知道有这三个命令类即可,至于命令类中封装好的逻辑,客户端则无需知道。

其次,命令模式的扩展性很好,在命令模式中,在接收者类中一般会对操作进行最基本的封装,命令类则通过对这些基本的操作进行二次封装,当增加新命令的时候,对命令类的编写一般不是从零开始的,有大量的接收者类可供调用,也有大量的命令类可供调用,代码的复用性很好。比如,文件的操作中,我们需要增加一个剪切文件的命令,则只需要把复制文件和删除文件这两个命令组合一下就行了,非常方便。

最后说一下命令模式的缺点,那就是命令如果很多,开发起来就要头疼了。特别是很多简单的命令,实现起来就几行代码的事,而使用命令模式的话,不用管命令多简单,都需要写一个命令类来封装。

命令模式的适用场景

对于大多数请求-响应模式的功能,比较适合使用命令模式,正如命令模式定义说的那样,命令模式对实现记录日志、撤销操作等功能比较方便。

总结

对于一个场合到底用不用模式,这对所有的开发人员来说都是一个很纠结的问题。有时候,因为预见到需求上会发生的某些变化,为了系统的灵活性和可扩展性而使用了某种设计模式,但这个预见的需求偏偏没有,相反,没预见到的需求倒是来了不少,导致在修改代码的时候,使用的设计模式反而起了相反的作用,以至于整个项目组怨声载道。这样的例子,我相信每个程序设计者都遇到过。所以,基于敏捷开发的原则,我们在设计程序的时候,如果按照目前的需求,不使用某种模式也能很好地解决,那么我们就不要引入它,因为要引入一种设计模式并不困难,我们大可以在真正需要用到的时候再对系统进行一下,引入这个设计模式。

拿命令模式来说吧,我们开发中,请求-响应模式的功能非常常见,一般来说,我们会把对请求的响应操作封装到一个方法中,这个封装的方法可以称之为命令,但不是命令模式。到底要不要把这种设计上升到模式的高度就要另行考虑了,因为,如果使用命令模式,就要引入调用者、接收者两个角色,原本放在一处的逻辑分散到了三个类中,设计时,必须考虑这样的代价是否值得。

感觉 Redux 有借鉴命令模式的思想

评论和共享

作者的图片

Archie Shi

Nothing to say


Front-End Development Engineer