組裝現有類成爲一個更大的結構,擴展出更強大的功能java
注:按重要程度排序
結構數據庫
適用場景設計模式
說明:經過一個代理對象控制原對象安全
有一句名言可讓咱們聯想下ide
計算機科學領域的任何問題均可以經過增長一個間接的中間層來解決
結構性能
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(); }
適用場景
結構
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); } }
適用場景
結構
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); ... } ... }
結構
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); } ... }
結構
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(); } }
適用場景
數據庫鏈接池
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(); } } } }
對於結構型的設計模式,主要是在解決類或對象間的組合關係,利用結構來實現解耦的問題,多用組合少用繼承,大部分仍是使用對象的組合來關聯他們
以上是一些學習總結及部分源碼,最關鍵的仍是在設計以前想好哪裏會變哪裏不大會變,這樣會更好的使用設計模式,並且不少設計模式也很類似,能夠參考說明對比他們的目的這樣能夠更好的理解
若有不正確的地方歡迎大佬指正