面向对象 设计模式 上

Posted by NotGeek on December 1, 2018

议题

  • 设计基石
  • 结构模式
  • 模式差异
  • 课堂小结
  • 问答互动

设计基石

  • 封装
    • 对象之间联系
  • 继承
    • 对象之间层次
  • 多态
    • 对象之间差异

对象之间的联系,调用,

父类,子类,继承

结构模式

  • 代理模式
  • 适配器模式
  • 装饰器模式
  • 享元模式
  • 组合模式
  • 门面模式
  • 桥接模式

适配器模式

  • 特点:将一个接口转换成为客户端的一个接口
  • 关系:适配接口和被适配接口没有层次关系
  • 距离:Java AWTJava I/OSpring Web MVC

java.awt.event.MouseListener 是观察者的变种。

java.awt.event.MouseAdapter

1
public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener {
  • 适配器可以有多实现,有滑轮,又有拖放

1542851351578

适配器:

字节流转化成为字符流,通过 Adapter 进行转化。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class FileDemo {
    public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException {
        // 目前拥有的实例
        InputStream inputStream = new FileInputStream("aaa");
        // 需要的对象
        // InputStream -> Reader
        Reader reader = new InputStreamReader(inputStream, "UTF-8");
        print(reader);
    }

    private static void print(Reader reader){
    }
}
1
2
3
4
5
6
7
@RestController
public class OopDesignPatternApplication extends WebMvcConfigurerAdapter {
    @GetMapping("")
    public String hello(){
        return "hello, world";
    }
}

装饰器模式

  • 特点:动态的添加或者覆盖被包装者的接口行为
  • 关系:装饰者和被装饰者有层次关系
  • 举例: Spring I/OSpring CoreSpring Web MVC

org.springframework.core.DecoratingClassLoader 就是继承加上多态。

享元模式

  • 特点:共享对象状态,减少重复创建
  • 关系:享元对象缓存共享实体
  • 举例:Integer 缓存String internThread Local

这个对象是经常用到的。

Integer

1
2
3
public static Integer valueOf(String s, int radix) throws NumberFormatException {
    return Integer.valueOf(parseInt(s,radix));
}

String

1
public native String intern();

ThreadLocal * ThreadlocalMap

享元模式和单例模式有异曲同工模式,

单例:双检查锁。

容器缓存也是,JVM 也是。

主要是 复用

组合模式

  • 特点:执行组合对象时如同执行其元素对象
  • 关系:组合对象和被组合对象是相同类型
  • 举例:EL Spring CacheSpring Web MVC

很重要,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class CompositeDemo {

    private static interface A{
        void save();
    }

    private static class AImpl implements A{
        @Override
        public void save() {
            System.out.println("save();");
        }
    }

    /**
     * 可实现可不实现
     **/
    private static class CompositeA implements A{
        private Collection<A> list = new ArrayList<>();
        @Override
        public void save() {
            list.forEach(a -> a.save());
        }
    }
}

逐一的去处理,迭代的去处理。(组合模式

1
2
3
4
5
6
7
8
9
10
11
12
public Object getValue(ELContext context, Object base, Object property) {
    context.setPropertyResolved(false);
    int sz = this.size;

    for(int i = 0; i < sz; ++i) {
        Object result = this.resolvers[i].getValue(context, base, property);
        if (context.isPropertyResolved()) {
            return result;
        }
    }
    return null;
}

org.springframework.cache.support.CompositeCacheManager

代理一般是一对一的关系

缓存,一层一层的缓存,只关心存储这件事情。

组合模式:

1542858962836

代理模式:

1542859063804

一般来说,

发消息,有可能是一对一,有可能是一对多。

org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite

1
2
3
4
class WebMvcConfigurerComposite implements WebMvcConfigurer {
    private final List<WebMvcConfigurer> delegates = new ArrayList();
	// ...
}

如果是相同类型,我感受不到是组合还是不是组合。

门面模式

  • 特点:简化接口,聚合子系统实现
  • 关系:门面接口和子系统接口自由组合实现
  • 举例:Tomcat

1542859771640

面向对象接口编程比较琐碎。A、B、C 数据属于相对独立的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class FacadeDemo {
    public static void main(String[] args) {

    }
    private static class ServiceA{
        private void save(){
        }
    }
    private static class ServiceB{
        private void save(){
        }
    }

    private static class ServiceFacade{
        private ServiceA serviceA;
        private ServiceB serviceB;
        private void service(){
            serviceA.save();
            serviceB.save();
        }
    }
}

总计

享元模式一对多,与业务没有太多的关系。

组合模式。多个元素组合执行

门面模式。多个子系统组合执行

接口爆炸,

缺点:

入参会比较复杂,调用链路越长,入参越多,越复杂,用户体验好,但是实现起来不好实现。

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
public class DispatcherServlet extends FrameworkServlet {
 
    private static final Properties defaultStrategies;
    private boolean detectAllHandlerMappings = true;
    private boolean detectAllHandlerAdapters = true;
    private boolean detectAllHandlerExceptionResolvers = true;
    private boolean detectAllViewResolvers = true;
    private boolean throwExceptionIfNoHandlerFound = false;
    private boolean cleanupAfterInclude = true;
    @Nullable
    private MultipartResolver multipartResolver;
    @Nullable
    private LocaleResolver localeResolver;
    @Nullable
    private ThemeResolver themeResolver;
    @Nullable
    private List<HandlerMapping> handlerMappings;
    @Nullable
    private List<HandlerAdapter> handlerAdapters;
    @Nullable
    private List<HandlerExceptionResolver> handlerExceptionResolvers;
    @Nullable
    private RequestToViewNameTranslator viewNameTranslator;
    @Nullable
    private FlashMapManager flashMapManager;
    @Nullable
    private List<ViewResolver> viewResolvers;

1542860510109

HandlerMapping 就是组合模式,

桥接模式

1542861170482

JDBC里边

Preparement

同时注入是策略模式。

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 class BirdgeDemo {
    public static void main(String[] args) {
        ScanService scanService = new scanServiceImpl(new ScanbuyService() {
            @Override
            public void buy() {
                System.out.println("JD 扫码购物");
            }
        }, null);

        // scanService.scanBuy() -> scanBuyService.buy();
        // 对于客户端而言,只关注与粗粒度接口,具体执行方法是由运行时初始化而定。
        scanService.scanbuy();


         scanService = new scanServiceImpl(new ScanbuyService() {
            @Override
            public void buy() {
                System.out.println("TaoBao 扫码购物");
            }
        }, null);

    }

    static class scanServiceImpl implements ScanService {
        private ScanbuyService scanbuyService;
        private ScanLoginService scanLoginService;

        scanServiceImpl(ScanbuyService scanbuyService, ScanLoginService scanLoginService) {
            this.scanbuyService = scanbuyService;
            this.scanLoginService = scanLoginService;
        }

        @Override
        public void scanbuy() {
            scanbuyService.buy();
        }

        @Override
        public void scanLogin() {
            scanLoginService.login();
        }
    }

    interface ScanService {
        void scanbuy();

        void scanLogin();
    }

    interface ScanbuyService {
        void buy();
    }

    interface ScanLoginService {
        void login();
    }
}

设计模式重要的是思想,

我调用你的时候,我才注入。