Hibernatede的優缺點,Struts的工做流程,延遲加載及理解開閉原則 遲加載與單例模式

Hibernate的優勢html

1.對象/關係數據庫映射(ORM)算法

它使用時只須要操做對象,使開發更對象化,拋棄了數據庫中心的思想,徹底的面對對象思想數據庫

2.透明持久化(persistent)編程

帶有持久化狀態、具備業務邏輯的單線程對象,此對象生存期很短。 這些對象多是普通的JavaBeans/POJO,這個對象沒有實現第三方框架或者接口,惟一特殊的是他們正在與(僅僅一個)Session相關聯。一旦這個Session被關閉,這些對象就會脫離持久化狀態,這樣就能夠被應用程序的任何層自由使用。(列如,用做跟表示層交互數據和傳輸對象)。數組

3.事務Transaction(org.hibernate.Transaction)緩存

應用程序用來指定原子操做的單元範圍的對象,它是單線程的,生命週期很短。他經過抽象將應用從底層具體的JDBC、JTA以及CORBA事務隔離開。某些狀況下,一個Session安全

以內可能包含多個Transaction對象。儘管是否使用該對象是可選的,但不管是使用底層的API仍是使用Transaction對象,事務邊界的開啓與關閉是必不可少的。
(4) 它沒有侵入性,即所謂的輕量級框架
(5) 移植性會很好
(6) 緩存機制,提供一級緩存和二級緩存
(7) 簡潔的HQL編程
 
2. Hibernate缺點
(1)  Hibernate在批量數據處理時有弱勢
(2) 針對單一對象簡單的增刪查改,適合於Hibernate,而對於批量的修改,刪除,不適合用Hibernate,這也是OR框架的弱點;要使用數據庫的特定優化機制的時候,不適合用Hibernate多線程

Struts2的工做流程app

請求在Struts2框架中的處理大概分爲如下幾個步驟: 1 客戶端初始化一個指向Servlet容器的請求; 2 這個請求通過一系列的過濾器(Filter)(這些過濾器中有一個叫作ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其餘框架的集成頗有幫助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請是否須要調用某個Action 4 若是ActionMapper決定須要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy 5 ActionProxy經過Configuration Manager詢問框架的配置文件,找到須要調用的Action類 6 ActionProxy建立一個ActionInvocation的實例。 7 ActionInvocation實例使用命名模式來調用,在調用Action的過程先後,涉及到相關攔截器(Intercepter)的調用。 8 一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果一般是(但不老是,也可 能是另外的一個Action鏈)一個須要被表示的JSP或者FreeMarker的模版。在表示的過程當中可使用Struts2 框架中繼承的標籤。在這個過程當中須要涉及到ActionMapper框架

 

 

遲加載與單例模式

延遲加載,也較延遲實例化,延遲初始化等,主要表達的思想就是,把對象的建立延遲到使用的時候建立,而不是對象實例化的時候建立。這種方式避免了性能的浪費。

當建立一個對象的子對象開銷比較大時,並且有可能在程序中用不到這個子對象,那麼久能夠考慮用延遲加載的方式來建立子對象。另外就是當一個程序啓動時,須要建立多個對象,但僅有幾個對象須要當即使用,那麼能夠將一些沒必要要的初始化工做延遲到使用的時候。這樣能夠提升程序的啓動速度。

FramWork4.0中提供了一個包裝類Lazy<T>,能夠輕鬆實現延遲加載。

今天就先從延遲加載開始學起。

1、延遲加載

一、Class Singleton

{

        private static Singleton instance;
      private Singleton()
      { }

      public static Singleton getInstance()

      {

         If(instance==null)

{

 Instance=new Singleton();

}

Return instance;

}

}

構造函數私有,方法靜態。

問題:沒法保證線程安全,當有多個線程同時訪問getInstance的時候,此時若對象爲空,就會出現會多個線程同時產生多個Singleton對象。

此時咱們能夠修改一下上面的代碼,以下

    public class Singleton
    {  
       private static Singleton instance;
       private static object _lock=new object();

       private Singleton()
       {

       }

       public static Singleton GetInstance()
       {
               if(instance==null)
               {
                      lock(_lock)
                      {
                             if(instance==null)
                            {
                                     instance=new Singleton();
                             }
                      }
               }
               return instance;
       }
    }

上述代碼使用了雙重鎖方式較好地解決了多線程下的單例模式實現。先看內層的if語句塊,使用這個語句塊時,先進行加鎖操做,保證只有一個線程能夠訪問該語句塊,進而保證只建立了一個實例。再看外層的if語句塊,這使得每一個線程欲獲取實例時沒必要每次都得加鎖,由於只有實例爲空時(即須要建立一個實例),才需加鎖建立,若果已存在一個實例,就直接返回該實例,節省了性能開銷。

二、若是使用以下的單例模式

class Singleton
{
 private static Singleton instance = new Singleton();
 private Singleton()
 {
    //
 }
 public static Singleton getInstance()
 {
    return instance;               
 }
}

這個方法保證了在第一次加載的時候實例被初始化,且保證了線程安全。可是爲進一步要求,咱們想要在使用的時候才才初始化Singleton對象,及延遲加載。那麼可使用以下方法。

三、延遲加載

public class Singleton {
    private Singleton(){
    }
   private static class SingletonHolder

 {
     static Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
    public static void main(String [] args)
    {
        Singleton.getInstance();
    }
}

方法中Singleton 有一個靜態內部類SingletonHolder,內部類在外部加載的時候並不會加載,在有在調用getInstance纔回加載。另外SingletonHolder類使用Private修飾以確保外部類不能訪問。

2、下面再看一個實例

namespace WebApplication2

{

 

    public partial class _Default : System.Web.UI.Page

    {

      

        protected void Page_Load(object sender, EventArgs e)

        {

            // 從數據庫中取出數據,獲得一個DateRow或者DateRader之類的東東而後初始化一個文章實體類對象

            Model_Article at = 。。。。;//at=getobject();

            // 建立文章分類數據訪問對象

            DAO_ArticleCategory articleCategory = new DAO_ArticleCategory();

            subArticle sarticle = new subArticle();

            sarticle.CategoryLazyLoader = articleCategory.GetArticleCategoryById;

            sarticle.CategoryLazyLoader(1);

            Model_ArticleCategory acc = at.Category;

            //

        }

 

    }

    // 文章分類實體類   

    public class Model_ArticleCategory

    {      

        public int CategoryID { get; set; }     

        public string CategoryName { get; set; }  

    }

    public class DAO_ArticleCategory

    {

        public Model_ArticleCategory GetArticleCategoryById(int i)

        {

            return new Model_ArticleCategory();

        }

    }

    // 文章實體類   

    public class Model_Article

    {       

        public int ArticleID { get; set; } 

        public string Title { get; set; }       

        public string Cotnent{ get; set; }       

        public DateTime CreateTime { get; set; }      

        public int CategoryID { get; set; }     

        // 文章所屬分類  

        protected Model_ArticleCategory _category;

        public virtual Model_ArticleCategory Category //聲明爲虛屬性

        {

            get

            {

               

                GetCategoryRecord += "獲取分類;";

                return _category;

            }

           

        }

        public string GetCategoryRecord { get; set; }

 

    }

    //繼承父類,把原來父類中得邏輯放到子類中來實現,保證了父類所處Model層沒有引用其餘業務層,保證了框架的規則

    public class subArticle : Model_Article

    {

        public override Model_ArticleCategory Category

        {

            get

            {

                if (base._category == null)

                {

                    if (CategoryLazyLoader != null)

                    {

                        _category = CategoryLazyLoader(CategoryID);

                    }

                    else

                    {

                        _category = null;

                    }   

                }

                return base.Category;

            }

        }

        // 文章分類延時加載器(委託)      

        public Func<int, Model_ArticleCategory> CategoryLazyLoader { get; set; }

    }

  

}

基類的Category屬性經過返回_category字段的方式返回值,也就是說數據是存在_category字段而不是屬性中,可是_category字段怎麼纔會有值呢,那就是在子類裏面經過調用委託拿來的,而這個屬性在子類裏面不是直接返回的,而是調用基類來返回,這樣一來,調用到子類的Category屬性的get訪問器的時候,先對基類的_categoty字段賦值,而後調用基類的Category屬性執行了一些邏輯代碼,最後成功地把(已經被賦值的)基類的_categoty字段給返回去。而這一切都是在前面咱們實現好的延遲加載的基礎上完成的。總結成幾個字就是:子類負責延時加載,基類賦值數據存儲和返回!

 

關閉原則的理解

開-閉原則:一個軟件實體應該對擴展開放,對修改關閉。


知足開閉原則的模塊符合下面兩個標準:

  • 對擴展開放 ------- 模塊的行爲能夠被擴展從而知足新的需求。
  • 對修改關閉 ------- 不容許修改模塊的源代碼。(或者儘可能使修改最小化)

這兩個標準看似相互矛盾的,那麼咱們怎麼實現他們呢?

怎樣實現開閉原則?

  • 抽象
  • 多態
  • 繼承
  • 接口
爲何要遵循開放關閉原則?        一個設計良好的應用程序應該充分考慮到開發和維護階段需求的頻繁變化,一般狀況下,添加一個新的功能須要作出不少修改,咱們應該使對已有代碼的修改最小化,由於他們已經通過了測試。對現有代碼作出修改將會以一種不可預料的方式影響它們的已有功能。
 
Example:

考慮下面某個類的方法:

 

Java代碼   收藏代碼
  1. public double totalPrice(Part[] parts) {  
  2.     double total = 0.0;  
  3.         for (int i=0; i<parts.length; i++) {  
  4.             total += parts[i].getPrice();  
  5.     }  
  6.     return total;  
  7. }  

 

上面函數的功能是計算給定的零件數組中全部零件價格的總和,若是Part是一個基類或者接口,那咱們就能夠利用多態的特性,當有新的零件被添加進來時不須要修改該函數的代碼。這樣它就能夠知足開閉原則。

 

可是若是咱們的會計部門規定當計算主板和內存的價格時,須要添加一些額外的費用,請看下面的代碼:

Java代碼   收藏代碼
  1. public double totalPrice(Part[] parts) {  
  2.   double total = 0.0;  
  3.   for (int i=0; i<parts.length; i++) {  
  4.     if (parts[i] instanceof Motherboard)  
  5.       total += (1.45 * parts[i].getPrice());  
  6.     else if (parts[i] instanceof Memory)  
  7.       total += (1.27 * parts[i].getPrice());  
  8.     else  
  9.       total += parts[i].getPrice();  
  10.   }  
  11.   return total;  
  12. }  

 

如今它還符合開閉原則嗎?不!每次會計部門發佈一個新的價格政策時,咱們都須要修改totalPrice()方法!它對修改不是關閉的,顯然,價格政策的改變意味着咱們必須修改某處的代碼,那麼咱們應該怎麼作呢?爲了使用咱們第一個版本的totalPrice()方法,咱們須要把Part的getPrice()方法的價格政策包含進來。

下面是Part和ConcretePrat類:

Java代碼   收藏代碼
  1. // Class Part is the superclass for all parts.  
  2. public class Part {  
  3.   private double price;  
  4.   public Part(double price) (this.price = price;}  
  5.   public void setPrice(double price) {this.price = price;}  
  6.   public double getPrice() {return price;}  
  7. }  
  8. // Class ConcretePart implements a part for sale.  
  9. // Pricing policy explicit here!  
  10. public class ConcretePart extends Part {  
  11.     public double getPrice() {  
  12. // return (1.45 * price); //Premium  
  13.       return (0.90 * price); //Labor Day Sale  
  14.     }  
  15. }  

 

可是,如今若是價格政策改變,咱們必須修改Part的子類,一個更好的方法是創建一個PricePolicy類,它能夠爲咱們提供不一樣的價格政策:

Java代碼   收藏代碼
  1. /** 
  2. * Class PricePolicy implements a given price policy. 
  3. */  
  4. public class PricePolicy {  
  5. private double factor;  
  6. public PricePolicy (double factor) {  
  7. this.factor = factor;  
  8. }  
  9. public double getPrice(double price) {return price * factor;}  
  10. }  

 

使用這種方法,咱們能夠在運行時動態的設置Part對象所引用的PricePoilcy對象,在實際的程序中,零件的價格和相關的PricePolicy能夠從數據庫中獲取。

 
理解:  在設計一個模塊的時候,應當使這個模塊能夠在不被修改的前提下被擴展。 
             其實這裏所說的不被修改是指的重要的抽象層的模塊不會被修改,這也就是使變化中的軟 系統有必定的穩定性。當系統要擴展或者添加新的行爲的時候只須要添加 另外實現的模塊便可。因爲新添加的模塊繼承於抽象層,因此實現了其不變性。 
              好比在策略模式中,OCP就獲得了很好的體現,算法的不一樣實現其實就是對擴展的支持,而算法抽象類是對系統的不變性的支持,環境類包裝了對於環境變化的控制與所採用算法的選擇,當採用其餘算法的時候只須要擴展算法類便可。  
               也就是說關鍵在於抽象,抽象出來的東西是不變的,具體的實 現繼承於抽象,因此保證了對修改的Close,而抽象的實現方式有多種,能夠隨需添加,固然這也就是對擴展的Open。 另外要求的是技術包括:多態 Polymorphism,接口 Interface,繼承 Inheritance.
 
 
注:另外在對可變性進行封裝的時候也應該注意如下幾點:            1.識別系統有可能變化的地方。            2.不要將一種可變形散佈在多處代碼,而應該封裝起來。            3.不要將一種可變性與另一種可變性混在一塊兒。
相關文章
相關標籤/搜索