面向对象 设计模式 下

Posted by NotGeek on December 17, 2018

本期议题

  • 行为模式
  • 模式差异

行为模式

  • 责任链模式
  • 拦截器模式
  • 观察者模式
  • 访问者模式
  • 调节者模式

责任链模式

Chain-of-responsibility pattern

1545023175238

1545023273337

模式:

非阻断模式
阻断模式

例子:

  • javax.servlet.Filter
  • java.util.logging.Filter

1545023706620

日志的输出,可能控制台输出一份,文件输出一份。就不是阻塞的,只不过是有先后顺序。

1545023985794

有一点点的边界。

1545024275625

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/***
 * NodeFilter1 -> Servlet1
 */
public class NodeFilter1 implements javax.servlet.Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if (true){
            // 条件式的阻断
            return;
        }

        /***
         * Before
         */

        // 执行下一个节点
        filterChain.doFilter(servletRequest,servletResponse);

        /***
         * After
         */
    }
}

Chain-of-responsibility pattern

From Wikipedia, the free encyclopedia

Jump to navigation

Jump to search

In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects.[1] Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain. Thus, the chain of responsibility is an object oriented version of the if ... else if ... else if ....... else ... endif idiom, with the benefit that the condition–action blocks can be dynamically rearranged and reconfigured at runtime.

img

Filter 有多个的时候首先要保证顺序。它是一个源,首先是一个 命令对象

Servlet 的程序设计需要理解很透彻。

数组的实现。

org.apache.catalina.core.ApplicationFilterChain
1
2
3
4
/**
 * Filters.  是一个数组的实现
 */
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];

有时候是没有处理逻辑的,并不是所有的都有 if ... else ... 的。

责任链的好处:

  • 解耦

    减少 if else 的 判断,把不同的节点进行一个切分。每个节点都有响应的处理的职责。至于它有没有逻辑处理要看节点里边有没有逻辑处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Servlet1 extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // + 1
        // + 2

        // save()  ->  Save Node
        // update()  ->  Update  Node (Servlet 2  用到了)
        // delete()   ->  Delete Node

        // servletFilter -> updateFilter  -> Servlet1
        // updateFilter  ->  Servlet2
    }
}

责任链模式的确很像责任链模式,就是一串的处理。看你怎么去表述,

拦截器模式

AOP 是典型的 拦截器模式。

AOP 是面向对象的一种讲法。但它的实质还是拦截。不要把 AOP 和 Spring 对等。Spring 只是用了 AOP 的东西,一种是 CGLB 一种是 JDK

Hibernate 里边的延迟查询的时候,需要用类的代理来做。

before after 是 c 里边的方式,

Java 里边还有一个 异常的时候

org.springframework.web.servlet.HandlerInterceptor

#####

1
2
3
4
5
6
7
8
9
10
11
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

structs 里边也有。

  • org.springframework.aop.MethodBeforeAdvice
  • org.springframework.aop.AfterReturningAdvice
  • org.springframework.aop.ThrowsAdvice

1545197303296

大多数学生还有面试官,有一大堆理论。

面试的时候要背着电脑去。

不因言而举人,不因言而废人。 –孔子

工厂模式大家都知道,你知道不会为你 加分

观察者模式

Observer, MQ 也可以算是一种观察者模式,只不过是分布式的。

维基百科:

Observer pattern

The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

It is mainly used to implement distributed event handling systems, in “event driven” software. Most modern languages such as C# have built in “event” constructs which implement the observer pattern components.

The observer pattern is also a key part in the familiar model–view–controller (MVC) architectural pattern.[1] The observer pattern is implemented in numerous programming libraries and systems, including almost all GUI toolkits.

notifies them automatically of any state changes

自动通知,任何的状态改变

有两种模式

  • 主动
  • 被动

拉的模式,主动去拉。

第二种方式去推。

观察者模式,它是一种推的模式。观察者模式有非常多的方式来进行表达。 JAVA 代码

java.util.Observer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Deprecated(since="9")
public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an {@code Observable} object's
     * {@code notifyObservers} method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the {@code notifyObservers}
     *                 method.
     */
    void update(Observable o, Object arg);
}

通知的对象,通知它的改变,

观察者其实也是一个订阅者。

1
2
3
4
5
6
7
public class Observable {
    private boolean changed = false;
    // List List 的一个实现, 有序的,可以重复的。
    private Vector<Observer> obs;
    // 方法上面都有 synchronized 关键字
   synchronized 。。。
}

Vecotor 就是 List

1
2
3
4
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
  • Observable 是一个维护有序的 Observer 集合 , Subject、Publisher
  • Observer = consumer = Subscriber

​ Java 本身不希望你去用 观察者模式 的时候直接去用,而是用到自己的场景里边的时候,不是直接用,而是根据自己的业务场景去做一些定制。

Observer 是一个接口 Observable 是一个抽象类。

先改变状态,才能去通知它。

一个源事件。

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
/***
 * 观察者模式 Demo
 * Observable 是一个维护有序的 Observer 集合 , Subject、Publisher
 * Observer = consumer = Subscriber
 */
public class ObserverDemo {
    public static void main(String[] args) {
        // JDk 存在观察者模式的实现。
        MyObservable observable = new MyObservable();

        observable.addObserver((o, arg) -> {
            System.out.println("观察者 1:邮件订阅:" + arg);
        });
        observable.addObserver((o, arg) -> {
            System.out.println("观察者 2:邮件订阅:" + arg);
        });
        observable.addObserver((o, arg) -> {
            System.out.println("观察者 3:邮件订阅:" + arg);
        });

        // 调整变化
        observable.setChanged();

        // 通知变化到所有观察者
        observable.notifyObservers("邮件通知:Hello, World");
    }

    private static class MyObservable extends Observable{
        // 子类提升方法从 protected 到 public
        @Override
        public synchronized void setChanged() {
            super.setChanged();
        }
    }
}

结合源码的方式可以更好的理解设计模式。

访问者模式

用的场景非常的有限。

Visitor pattern

img

visitor 模式会将一些东西进行耦合。

1545226189126

对于登陆的业务而言,不管你是哪里来的。

缺点:

visitor 模式增加业务的时候不得不去增加一个方法。你中有我,我中有你,会变得非常的复杂。

好处:

无需关心你的什么方式,我只需要关心我的接口,上下游两个接口是相互耦合的,但是屏蔽了很多细节。

调节者模式

不太好理解

Mediator pattern

In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program’s running behavior.

  • 高度封装 字段 private (encapsulates)
  • 对象 一大堆对象 ( how a set of objects)
  • 交互 (interact)

技术 - 数量 - 交互

我用一个方法交互很多东西。

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

//Colleague interface
interface Command {
    void execute();
}

//Abstract Mediator
interface Mediator {
    void book();
    void view();
    void search();
    void registerView(BtnView v);
    void registerSearch(BtnSearch s);
    void registerBook(BtnBook b);
    void registerDisplay(LblDisplay d);
}

//Concrete mediator
class ParticipantMediator implements Mediator {

    BtnView btnView;
    BtnSearch btnSearch;
    BtnBook btnBook;
    LblDisplay show;

    //....
    public void registerView(BtnView v) {
        btnView = v;
    }

    public void registerSearch(BtnSearch s) {
        btnSearch = s;
    }

    public void registerBook(BtnBook b) {
        btnBook = b;
    }

    public void registerDisplay(LblDisplay d) {
        show = d;
    }

    public void book() {
        btnBook.setEnabled(false);
        btnView.setEnabled(true);
        btnSearch.setEnabled(true);
        show.setText("booking...");
    }

    public void view() {
        btnView.setEnabled(false);
        btnSearch.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("viewing...");
    }

    public void search() {
        btnSearch.setEnabled(false);
        btnView.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("searching...");
    }
    
}

//A concrete colleague
class BtnView extends JButton implements Command {

    Mediator med;

    BtnView(ActionListener al, Mediator m) {
        super("View");
        addActionListener(al);
        med = m;
        med.registerView(this);
    }

    public void execute() {
        med.view();
    }
    
}

//A concrete colleague
class BtnSearch extends JButton implements Command {

    Mediator med;

    BtnSearch(ActionListener al, Mediator m) {
        super("Search");
        addActionListener(al);
        med = m;
        med.registerSearch(this);
    }

    public void execute() {
        med.search();
    }
    
}

//A concrete colleague
class BtnBook extends JButton implements Command {

    Mediator med;

    BtnBook(ActionListener al, Mediator m) {
        super("Book");
        addActionListener(al);
        med = m;
        med.registerBook(this);
    }

    public void execute() {
        med.book();
    }

}

class LblDisplay extends JLabel {

    Mediator med;

    LblDisplay(Mediator m) {
        super("Just start...");
        med = m;
        med.registerDisplay(this);
        setFont(new Font("Arial", Font.BOLD, 24));
    }

}

class MediatorDemo extends JFrame implements ActionListener {

    Mediator med = new ParticipantMediator();

    MediatorDemo() {
        JPanel p = new JPanel();
        p.add(new BtnView(this, med));
        p.add(new BtnBook(this, med));
        p.add(new BtnSearch(this, med));
        getContentPane().add(new LblDisplay(med), "North");
        getContentPane().add(p, "South");
        setSize(400, 200);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent ae) {
        Command comd = (Command) ae.getSource();
        comd.execute();
    }

    public static void main(String[] args) {
        new MediatorDemo();
    }

}

​ 我用一个对象来交互很多东西,注册一个视图,book,搜索。

​ 你点观察的时候,就改变了状态了。

​ 我音量 + - 的时候, 这个图像变化,音量也减少了,类似于这种操作。

​ 把复杂的东西都是有关联的。

调节者模式:

1545235955552

这个操作是,协调整个,

例子: 猫,调制解调器。要把模拟信号,变成数字信号。

都是 Object ,协调里边的一些情况,

在图形化界面种比较多。

和状态模式比较像,但是呢,状态模式多关注于单个状态, 调节者是一系列状态。

假设整个浏览器是一个协调者,就是你点一下,整个就变化了。

门面模式:

1545236212672

门面模式与调节者模式:

都是一个统一入口,门面模式是把一系列操作进行合成,不能是协调,

而调节者模式,里边的那几个对象是有状态的,还有协调的关系。

责任链模式:

1545236336385

责任链模式是对等的。

你可以用责任链模式实现门面模式,

总结:

你可以用多种组合实现一种方式,它既可以像雨,又可以像风

wapper 和 adapter 很像,

​ 关键在于数据结构,你就是搞一个数据过着类的结构,其实你可以认为流程的协调,状态的协调。都可以讲的通。