設計模式-結構型

寫在前面

  1. 什麼是結構型的設計模式

    • 類結構型:多個類組合成更大的類,只存在類繼承和實現關係
    • 對象結構型:類和對象組合的關聯關係,根據合成複用原則,儘可能使用關聯關係代替繼承
  2. 爲何要用

    組裝現有類成爲一個更大的結構,擴展出更強大的功能java

模式類型

注:按重要程度排序
  1. 外觀模式(Facade)

    • 說明:統一方法對象訪問內部接口
    • 結構數據庫

      • Facade
      • SubInterface
    • 適用場景設計模式

      • 經常使用的MVC分層就是一種外觀模式,好比service層聚合了dao
      • 統一接入的API網關
  2. 代理模式(Proxy)

    • 說明:經過一個代理對象控制原對象安全

      有一句名言可讓咱們聯想下ide

      計算機科學領域的任何問題均可以經過增長一個間接的中間層來解決
    • 結構性能

      • Proxy:代理類
      • Source:被代理類
      • SourceImpl:學習

        靜態代理:代理和被代理對象都須要實現目標接口,在運行前就有Class文件了優化

        動態代理:代理類和被代理類有一種關聯關係,動態生成字節碼加載到JVM中,編譯完沒有Class文件this

        • JDK動態代理:依靠反射機制獲取接口實現
        • Cglib動態代理:對目標類生成子類以覆蓋其子類方法

        以下是一個靜態代理的實現,可是擴展的時候須要一個類一個代理類,過多冗餘因此又有了動態代理url

        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動態代理

        // 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動態代理

        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:容器

        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:適配器

        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,字節變字符

            //  對象適配
            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);
                    ...
                }
              ...
            }
  5. 裝飾器模式(Decorator)

    • 說明:動態的給目標對像添加新功能
    • 結構

      • Component:抽象組件
      • ConcreteComponet:具體組件
      • Decorator:裝飾器
      • ConcreteDecorator:具體實現

        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();
            }
        }
        • 適用場景

          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);
              }
            ...
          }
  6. 橋接模式 (Bridge)

    • 說明:使抽象和實現能夠各自獨立的變化
    • 結構

      • Bridge
      • Destination

        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();
            }
        }
  7. 享元模式(蠅量,FlyWeight)

    • 說明:經過共享技術來有效的支持大量細粒度的對象
    • 適用場景

      • 數據庫鏈接池

        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 類圖及排版優化

若有不正確的地方歡迎大佬指正

相關文章
相關標籤/搜索