设计模式-结构型

写在前面

  1. 什么是结构型的设计模式
    • 类结构型:多个类组合成更大的类,只存在类继承和实现关系
    • 对象结构型:类和对象组合的关联关系,根据合成复用原则,尽量使用关联关系代替继承
  2. 为什么要用

    组装现有类成为一个更大的结构,扩展出更强大的功能

模式类型

注:按重要程度排序

  1. 外观模式(Facade)
    • 说明:统一方法对象访问内部接口
    • 结构
      • Facade
      • SubInterface
    • 适用场景
      • 常用的MVC分层就是一种外观模式,比如service层聚合了dao
      • 统一接入的API网关
  2. 代理模式(Proxy)
    • 说明:通过一个代理对象控制原对象

      有一句名言可以让我们联想下

      计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决

    • 结构

      • Proxy:代理类

      • Source:被代理类

      • SourceImpl:

        静态代理:代理和被代理对象都需要实现目标接口,在运行前就有Class文件了

        动态代理:代理类和被代理类有一种关联关系,动态生成字节码加载到JVM中,编译完没有Class文件

        • JDK动态代理:依靠反射机制获取接口实现
        • Cglib动态代理:对目标类生成子类以覆盖其子类方法

        如下是一个静态代理的实现,但是扩展的时候需要一个类一个代理类,过多冗余所以又有了动态代理

        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 class ProxyTest {
        public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.invoke();
        }
        }

        interface Source {
        void invoke();
        }

        class Sourceable implements Source {
        @Override
        public void invoke() {
        System.out.println("real invoke");
        }
        }

        class Proxy implements Source {
        @Override
        public void invoke() {
        before();
        Sourceable sourceable = new Sourceable();
        sourceable.invoke();
        after();
        }
        // 增强功能
        private void after() {
        System.out.println("after");
        }

        private void before() {
        System.out.println("before");
        }
        }
      • jdk动态代理

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        /**
        * jdk动态代理
        */
        @AllArgsConstructor
        class JdkProxy implements InvocationHandler {
        private Object target;

        @Override
        public Object invoke(Object SelfProxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = method.invoke(target, args);
        System.out.println("after");
        return result;
        }
        }
        // 调用入口,
        public static void jdkProxy(){
        // 原理:通过反射获取接口方法对象,所以必须依赖接口
        Source source = (Source)Proxy.newProxyInstance(Source.class.getClassLoader(),
        new Class[]{Source.class},
        new JdkProxy(new Sourceable()));
        source.invoke();
        }
      • cglib动态代理

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        class CglibProxy implements MethodInterceptor {

        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("after");
        return result;
        }
        }
        //调用入口
        public static void cglibProxy() {
        // 原理:对目标类生成一个子类,覆盖其中方法,所以不能对final修饰的方法
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(ProxyTarget.class);
        enhancer.setCallback(new CglibProxy());
        ProxyTarget proxyTarget = (ProxyTarget) enhancer.create();
        proxyTarget.invoke();
        }
    • 适用场景

      • Aop:日志记录/性能统计/安全控制/事物处理/异常处理
  3. 组合模式 (Composite)
    • 说明:组合成为体现”部分-整体”的分层结构,并且例如树结构

    • 结构

      • Component:抽象

      • Leaf:叶子结点

      • Composite:容器

        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
        public class CompositeTest {
        public static void main(String[] args) {
        AbstractComponent tree = new Tree("1", "parent");
        AbstractComponent sub2 = new TreeNode("2", "sub2");
        AbstractComponent sub3 = new TreeNode("3", "sub3");
        sub2.add(sub3);
        tree.add(sub2);
        tree.print();
        sub2.print();
        sub3.print();

        }
        }

        interface AbstractComponent {
        void add(AbstractComponent abstractComponent);

        void print();
        }

        @Data
        class Tree implements AbstractComponent {
        private String layer;
        private String name;
        private List<AbstractComponent> children = new ArrayList();

        public Tree(String layer, String name) {
        this.name = name;
        this.layer = layer;
        }

        @Override
        public void add(AbstractComponent abstractComponent) {
        this.children.add(abstractComponent);
        }

        @Override
        public void print() {
        System.out.println(layer + "|----|" + name);
        }
        }

        @Data
        class TreeNode implements AbstractComponent {
        private String layer;
        private String name;
        private List<AbstractComponent> children = new ArrayList();

        public TreeNode(String layer, String name) {
        this.name = name;
        this.layer = layer;
        }

        @Override
        public void add(AbstractComponent abstractComponent) {
        this.children.add(abstractComponent);
        }

        @Override
        public void print() {
        System.out.println(layer + "|----|" + name);
        }
        }
    • 适用场景

      • 比如部门组织列表
  4. 适配器模式(Adapter)
    • 说明 : 将一个类的方法接口转换为另一类的接口

    • 结构

      • Target:目标类
      • Adaptee:被适配者
      • 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
      32
      33
      34
      35
      36
      37
      38
      public class AdapterTest {
      public static void main(String[] args) {
      Target classAdapter = new ClassAdapter();
      classAdapter.invoke();
      Target objApapter = new ObjectAdapter(new Adaptee());
      objApapter.invoke();
      }
      }

      interface Target {
      void invoke();
      }

      class Adaptee {
      public void concreteInvoke() {
      System.out.println("real invoke");
      }
      }

      // 类适配器,通过继承
      class ClassAdapter extends Adaptee implements Target {

      @Override
      public void invoke() {
      super.concreteInvoke();
      }
      }

      // 对象适配器,通过组合(最常用)
      @AllArgsConstructor
      class ObjectAdapter implements Target {
      private Adaptee adaptee;

      @Override
      public void invoke() {
      adaptee.concreteInvoke();
      }
      }
  • 适用场景

    • JDK: InputSream -> Reader , OutputStream -> Writer,字节变字符

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      //  对象适配
      public class InputStreamReader extends Reader {
      private final StreamDecoder sd;
      public InputStreamReader(InputStream in) {
      super(in);
      ...
      }
      ...
      }

      public class OutputStreamWriter extends Writer {
      private final StreamEncoder se;
      public OutputStreamWriter(OutputStream out, String charsetName)
      throws UnsupportedEncodingException{
      super(out);
      ...
      }
      ...
      }
  1. 装饰器模式(Decorator)
    • 说明:动态的给目标对像添加新功能

    • 结构

      • Component:抽象组件

      • ConcreteComponet:具体组件

      • Decorator:装饰器

      • ConcreteDecorator:具体实现

        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
        public class DecoratorTest {
        public static void main(String[] args) {
        Component component = new ConcreteComponet();
        Decorator decorator = new ConcreteDecorator(component);
        decorator.opertion();
        }
        }

        interface Component {
        void opertion();
        }

        class ConcreteComponet implements Component {

        @Override
        public void opertion() {
        System.out.println("doing sth");
        }
        }

        // 装饰器
        class Decorator implements Component {
        private Component component;

        public Decorator(Component component){
        this.component = component;
        }

        @Override
        public void opertion() {
        component.opertion();
        }
        }
        // 通过对象组合
        class ConcreteDecorator extends Decorator {
        public ConcreteDecorator(Component component) {
        super(component);
        }

        @Override
        public void opertion() {
        System.out.println("增加了新功能");
        super.opertion();
        }
        }
  • 适用场景

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public abstract class InputStream implements Closeable {
    ...
    }

    public class FilterInputStream extends InputStream {
    protected volatile InputStream in;
    protected FilterInputStream(InputStream in) {
    this.in = in;
    }
    ...
    }
    // 装饰器实现,变化的部分
    public class DataInputStream extends FilterInputStream implements DataInput {
    public DataInputStream(InputStream in) {
    super(in);
    }
    ...
    }
  1. 桥接模式 (Bridge)
    • 说明:使抽象和实现可以各自独立的变化

    • 结构

      • Bridge

      • Destination

        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 class BridgeTest {
        public static void main(String[] args) {
        Destination destinationA = new DestinationA();
        Destination destinationB = new DestinationB();
        Bridge bridge = new Bridge(destinationB);
        bridge.bridgeDestination();
        }
        }

        interface Destination {
        void arrive();
        }

        class DestinationA implements Destination {

        @Override
        public void arrive() {
        System.out.println("A");
        }
        }

        class DestinationB implements Destination {

        @Override
        public void arrive() {
        System.out.println("B");
        }
        }

        class Bridge {
        private Destination destination;
        public Bridge(Destination destination){
        this.destination = destination;
        }
        public void bridgeDestination() {
        destination.arrive();
        }
        }
  2. 享元模式(蝇量,FlyWeight)
    • 说明:通过共享技术来有效的支持大量细粒度的对象

    • 适用场景

      • 数据库连接池
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      class ConnectionPool {
      ...
      @SneakyThrows
      private ConnectionPool() {
      pool = new Vector<Connection>(poolSize);
      for (int i = 0; i < poolSize; i++) {
      try {
      Class.forName(driverClassName);
      conn = DriverManager.getConnection(url, username, password);
      pool.add(conn);
      } catch (ClassNotFoundException e) {
      e.printStackTrace();
      } catch (SQLException e) {
      e.printStackTrace();
      }
      }
      }
      }
      • 线程池

        总结

​ 对于结构型的设计模式,主要是在解决类或对象间的组合关系,利用结构来实现解耦的问题,多用组合少用继承,大部分还是使用对象的组合来关联他们

​ 以上是一些学习总结及部分源码,最关键的还是在设计之前想好哪里会变哪里不大会变,这样会更好的使用设计模式,而且很多设计模式也很相似,可以参考说明对比他们的目的这样可以更好的理解

Todo 类图及排版优化

如有不正确的地方欢迎大佬指正