簡體   English   中英

如何有效地實施彈簧戰略模式?

[英]How to efficiently implement a strategy pattern with spring?

我有一個使用Spring框架在Java 1.5中開發的Web應用程序。 應用程序包含“儀表板”,這是一個簡單的頁面,其中一組信息被重新分組,用戶可以在其中修改某些狀態。 管理人員希望我在數據庫中為三個儀表板添加日志記錄系統。 每個儀表板都有不同的信息,但日志應該按日期和用戶的登錄進行跟蹤。

我想做的是實現類似這樣的策略模式:

interface DashboardLog {
   void createLog(String login, Date now);
}

// Implementation for one dashboard
class PrintDashboardLog implements DashboardLog {
  Integer docId;
  String status;

  void createLog(String login, Date now){
    // Some code
  }
}

class DashboardsManager {
  DashboardLog logger;
  String login;
  Date now;

  void createLog(){
     logger.log(login,now);
  }
}

class UpdateDocAction{
   DashboardsManager dbManager;

   void updateSomeField(){
      // Some action
      // Now it's time to log
      dbManagers.setLogger = new PrintDashboardLog(docId, status);
      dbManagers.createLog();
   } 
}

Appcontext.xml:

<bean id="dashboardManagers" class="...DashboardManagers" />

在這個解決方案中,我因此不使用依賴注入。 以這種方式做到這一點是“正確的”(良好做法,表現......) 有沒有更好的方法可以使用DI?

注意:我沒有編寫像constructor和getter / setter這樣的基本內容。

您的解決方案將為每次調用updateSomeField()創建一個新的PrintDashboardLog實例。 這可能會占用不必要的時間/內存/ GC工作量。 此外,從設計的角度來看,如果每個儀表板都有一個DashboardLog,而不是每個呼叫都有一個新儀表板,則這是有意義的。

我認為使用Logging是示例性用例之一的方面可能是個好主意。 就像是:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                            http://www.springframework.org/schema/aop
                            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <bean id="loggingAspect" class="com.yourcompany.yourapplication.aspects.DashboardLogAspect" />

    <aop:aspectj-autoproxy>
        <aop:include name="loggingAspect" />
    </aop:aspectj-autoproxy>

</beans>    


package com.yourcompany.yourapplication.aspects;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class DashboardLogAspect {

    @Around("execution(* com.yourcompany.yourapplication..*Action+.*(..)) && target(target)")
    public Object logActionCall(ProceedingJoinPoint pjp, Object target) throws Throwable {

        long before = System.nanoTime();

        Object returnValue = pjp.proceed();

        long after = System.nanoTime();
        long durationNs = after - before;

        String logMsg = target.getClass() + "." + pjp.getSignature().toShortString() + " (" + durationNs + " ns)";

        // TODO: store the log message in your database
        System.out.println(logMsg);

        return returnValue;
    }            
}

這會記錄對名稱以“Action”結尾的應用程序類的所有調用。 它還會增加每個呼叫完成所需的時間。 您可能還想調整特定方法名稱模式的Around建議。 請參閱AspectJ編程指南

雖然使用策略模式完全“正確”,但考慮到你使用Spring的事實 - 最好采用Spring框架提供的依賴注入機制 - 不妨使用什么您的框架必須提供其核心優勢之一。

如果每個“儀表板”都有一個控制器,為什么不從控制器調用日志記錄。


public interface DashboardLog
{
    void createLog(...);
}

public class DashboardUno
implements DashboardLog
{
    ...
    public void createLog(...)
    { ... }
}

@Controller
@RequestMapping("/blah/schmarr")
public class BlahController
{
    ...
    @RequestMapping(value = "/xxx")
    public String someMeaningfulName(...)
    {
        DashboardUno elEsUno;
        ... get the dashboard object ...
        elEsUno.createLog(...);
        ...
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM