Java Design Pattern

●Factory是什麼:java

工廠模式同單例模式同樣,也是Java中最經常使用的設計模式之一,屬於建立型模式,它提供了一種建立對象的最佳方式。可以根據要求調用者提供的信息爲接口指定不一樣的實現類,下降耦合。設計模式

●接口及其實現類:ide

package factory;

public interface Sender {
    public void send();
}

  

package factory;

public class SmsSender implements Sender{

    @Override
    public void send() {
        System.out.println("用短信發送...");
    }
}
package factory;

public class EmailSender implements Sender{

    @Override
    public void send() {
        System.out.println("用電子郵箱發送...");
    }

 

●簡單工廠優化

package factory;
/**
 * 普通工廠模式,能夠需求生產對象
 * 缺點:面對複雜的初始化,會使代碼變得巨大
 *      每添加一個實現類都要修改代碼,違反了里氏替換原則
 *      可能會產生null對象,引起 空指針異常
 * @author wqj24
 *
 */
public class GeneraSenderFactory {
    
    public Sender produceSender(String msg) {
        
        // 根據消息,指定具體實現類
        if ("email".equals(msg)) {
            return new EmailSender();
        }
        
        if ("sms".equals(msg)) {
            return new SmsSender();
        } 
        
        // 沒有符合要求的產品
        return null;
    }
}

上代碼每寫一個一個實現類就要就要改工廠類的代碼,很不方便。能夠經過反射解決這一問題。this

●簡單工廠(反射)spa

package factory;
/**
* 簡單工廠的優化
* 優勢:使用反射,避免了添加子類就要修改工廠對象
*/
public class GeneraSenderFactory01 { public Sender produceSender(Class<? extends Sender> clazz) { Sender sender = null; try { sender = (Sender) clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return sender; } }

在面對初始化複雜的對象時。反射的代碼會很長,且結構性差,能夠爲每一個子類都寫一個工廠方法prototype

●多個工廠方法設計

package factory;

/**
 * 多工廠,每一個方法負責生產各自的實例 優勢能夠應對複雜的初始化
 * 優勢:不會產生 null 對象
 *      每一個方法負責本身對象的初始化工做,結構清晰。
 */
public class ManySenderFactory {
    
    public Sender produceEmail() {

        return new EmailSender();
    }

    public Sender produceSms() {

        return new SmsSender();
    }
}

也能夠將上面的方法改寫成靜態的,這樣就能夠不用new對象,直接經過類名調用工廠方法了。代理

●Singleton:指針

  • 單例模式,確保某個類只能生成一個實例
  • 單例模式的構造方法必須定義爲私有(private)的
  • 必需要定義一個靜態(static)的方法,做爲生成這個對象實例的入口
    package com.singleton;  
    //靜態代碼塊不必定在最開始執行,好比說 靜態代碼塊 放在 單例模式中,  
    //但通常狀況下 靜態代碼塊是第一執行的 也就是在類加載時執行, 只執行一次  
    class SingletonTest  
    {  
        private static SingletonTest singletonTest = new SingletonTest();  
        static  
        {  
            System.out.println("======java 靜態代碼塊========");  
        }  
      
      
        private SingletonTest()  
        {  
            System.out.println("java實現單例模式");  
        }  
          
        public static SingletonTest getInstance()  
        {  
      
            return singletonTest;  
        }  
      
    }  
      
    public class Singleton  
    {  
        public static void main(String[] args)  
        {  
            SingletonTest st = SingletonTest.getInstance();  
            SingletonTest st2 = SingletonTest.getInstance();  
    
                      //返回true,這兩個實例是同樣的  
        System.out.println(st == st2);  
    }  

    prototype:

      原型模式雖然是建立型的模式,可是與工程模式沒有關係,從名字便可看出,該模式的思想就是將一個對象做爲原型,對其進行復制、克隆,產生一個和原對象相似的新對象。本小結會經過對象的複製,進行講解。在Java中,複製對象是經過clone()實現的,先建立一個原型類:

public class Prototype implements Cloneable {  
  
    public Object clone() throws CloneNotSupportedException {  
        Prototype proto = (Prototype) super.clone();  
        return proto;  
    }  
}

很簡單,一個原型類,只須要實現Cloneable接口,覆寫clone方法,此處clone方法能夠改爲任意的名稱,由於Cloneable接口是個空接口,你能夠任意定義實現類的方法名,如cloneA或者cloneB,由於此處的重點是super.clone()這句話,super.clone()調用的是Object的clone()方法,而在Object類中,clone()是native的,具體怎麼實現,我會在另外一篇文章中,關於解讀Java中本地方法的調用,此處再也不深究。在這兒,我將結合對象的淺複製和深複製來講一下,首先須要瞭解對象深、淺複製的概念:

  淺複製:將一個對象複製後,基本數據類型的變量都會從新建立,而引用類型,指向的仍是原對象所指向的。

  深複製:將一個對象複製後,不管是基本數據類型還有引用類型,都是從新建立的。簡單來講,就是深複製進行了徹底完全的複製,而淺複製不完全。

proxy:

動態代理(運行期行爲)主要有一個 Proxy類 和一個 InvocationHandler接口

動態代理角色:

1. 抽象主題角色

2. 真實主題角色(實現了抽象主題接口)

3. 動態代理主題角色(實現了 InvocationHandler接口,並實現了 invoke()方法)

Proxy 要調用 newProxyInstance方法

 

代碼演示:

 

1.抽象主題角色 SubjectDemo.java

package com.dynamicproxy ;  
  
public interface SubjectDemo  
{  
    public void request() ;  
}

2. 真實主題角色 RealSubjectDemo.java

package com.dynamicproxy ;  
  
  
public class RealSubjectDemo implements SubjectDemo  
{  
    public void request()  
    {  
        System.out.println("實現了某請求") ;  
    }  
}  

3. 動態代理主題角色 DynamicProxySubjectDemo.java

package com.dynamicproxy ;  
  
import java.lang.reflect.InvocationHandler ;  
import java.lang.reflect.Method ;  
  
  
public class DynamicProxySubjectDemo implements InvocationHandler  
{  
    private Object sub ;  
  
    public DynamicProxySubjectDemo(Object obj)  
    {  
        this.sub = obj ;  
    }  
  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  
    {  
        System.out.println("before"+method) ;  
  
        method.invoke(sub, args) ;//真實的調用方法操做  
  
        System.out.println("after"+method) ;  
  
        return null ;  
  
    }  
  
  
}  

4.客戶端 Client.java

package com.dynamicproxy ;  
  
import java.lang.reflect.InvocationHandler ;  
import java.lang.reflect.Proxy ;  
  
public class Client  
{  
    public static void main(String[] args)  
    {  
        RealSubjectDemo rsd = new RealSubjectDemo() ;  
  
        InvocationHandler handler = new DynamicProxySubjectDemo(rsd) ;  
         
        Class<?> classType = handler.getClass() ;  
          
        // classType.getClassLoader() 動態代理類的類加載器  
        //rsd.getClass().getInterfaces() 代理類要實現的接口列表  
        //handler 指派方法調用的調用處理程序  
        SubjectDemo sd = (SubjectDemo)Proxy.newProxyInstance(classType.getClassLoader(), rsd.getClass().getInterfaces(), handler ) ;  
          
        //這行代碼一執行 轉到 InvocationHandler handler = new DynamicProxySubjectDemo(rsd)  
         //執行invoke方法  
        sd.request() ;  
    }  
} 
相關文章
相關標籤/搜索