java - 适合报表系统的设计模式

标签 java oop design-patterns

在方法main中,我有String page,其中包含一些大文本,以及这样的代码:

List<String> wordsList = getWordsList(page);
System.out.println("Total number of words is: " + wordsList.size());

Map<String, Long> wordsSortedMap = getWordsSortedMap(wordsList);
wordsSortedMap.forEach((k, v) -> System.out.println(v + "\t" + k));

如您所见,我只是使用 util 方法 getWordsListgetWordsSortedMap 来构造所需的数据并将其打印到控制台。

我希望更改程序以实现可扩展,以便能够在不更改现有代码的情况下添加新类型的报告。

例如,输入数据始终是此 page 变量。例如,在 main 中可能是这样的:

ReportsExecutor.printReportOne(page);
ReportsExecutor.printReportTwo(page);

或者这个:

ReportOne reportOne = new ReportOne(page);
ReportTwo reportTwo = new ReportTwo(page);
reportOne.execute();
reportTwo.execute();

因此,要添加新的报告类型,我只需实现新的方法或类等。

是否有适合这种情况的设计模式或任何 OOP 最佳实践?

最佳答案

因为我强烈认为你的问题主要是关于 OOP,所以我将用 C# 做一个例子(因为我最精通)。

这个想法是使用构建器和访问者模式的组合来处理报表。

首先,我定义了 Report 类,如下所示(非常原始):

public interface IReport
{
    void Print();
}

public class Report : IReport
{
    private readonly IList<string> lines;

    public Report()
    {
        lines = new List<string>();
    }

    public void AddLine(string line)
    {
        lines.Add(line);
    }
    public void Print()
    {
        foreach (var l in lines) Console.Out.WriteLine(l);
    }
}

然后我定义了构建器的接口(interface):

public interface IReportBuilder
{
    void Execute();
    IReport Product { get; }
}

以及适合我们需求的访客:

public interface IWordVisitor
{
    void VisitWord(string word);
}

页面单词统计的实现如下所示:

public class PageStatisticVisitor : IWordVisitor
{
    private readonly IDictionary<string, long> stats;

    public PageStatisticVisitor()
    {
        stats = new Dictionary<string, long>();
    }

    public IDictionary<string, long> Stats { get { return stats; } }

    public void VisitWord(string word)
    {
        long currentStat;
        if (stats.TryGetValue(word, out currentStat)) currentStat++;
        else currentStat = 1;
        stats[word] = currentStat;
    }
}

(仅计算文本中相同的单词)。

我将页面内容封装到现在访问者的 Page 类中:

 public class Page
{
    private string pageContent;
    public Page(string content)
    {
        pageContent = content;
    }

    public void Accept(IWordVisitor visitor)
    {
        foreach (var w in pageContent.Split())
        {
            visitor.VisitWord(w);
        }
    }
}

单词统计报告生成器:

public class WordStatisticsBuilder : IReportBuilder
{
    private Report report;
    private Page page;

    public WordStatisticsBuilder(Page page)
    {
        report = new Report();
        this.page = page;
    }

    public void Execute()
    {
        var psv = new PageStatisticVisitor();
        page.Accept(psv);            
        foreach (var s in psv.Stats)
        {
            report.AddLine(string.Format("{0} : {1}", s.Key, s.Value));
        }
    }

    public IReport Product
    {
        get { return report; }
    }
}

用法:

var page = new Page(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");

        var statistics = new WordStatisticsBuilder(page);
        statistics.Execute();

        statistics.Product.Print();

我希望您有一个想法并且可以在 JAva 中实现它。

关于java - 适合报表系统的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45081372/

相关文章:

java - ABS - fragment - 菜单膨胀问题

java - Camel Splitters 执行后会保留交换主体吗?

iphone - 过程代码,vs oopy 代码和性能

c++ - 游标与迭代器模式

ios - MVC 中应用了哪些 OOP 概念?

database - 设计模式 : Should a factory update and delete too?

java - 哪些版本的 Kotlin 与哪些版本的 JDK 兼容?

Java synchronized 似乎被忽略了

python - Python中除了实例方法、静态方法、类方法之外,还有第四种方法吗?

c# - 如果一个方法不访问 "this"对象属性或方法,我们是否应该始终将它声明为静态方法