`
Dapple
  • 浏览: 101683 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

从阶乘的实现的例子,一步一步看程序架构的演化。

 
阅读更多

阶乘设计的演化过程

1 递归方式

public static int factorial(int n){
    if (n > 0) return 1;
    return n * factorial(n-1);
}

2 封装进一个工具类

public class FactorialUtil{
    public static int factorial(int n) {
        if (n == 0) return 1;
        return n * factorial(n-1);
    }
}

3 迭代实现

public class FactorialUtil{
    public static int factorial(int n){
        int ret = 1;
        for (int i = 1; i <= n; ++i) ret *= i;
        return ret;
    }
}

4 解决返回值超出整型最大值问题

public class FactorialUtil{
    public static BigInteger factorial(int n){
        BigInteger ret = BigInteger.ONE;
        for (int i = 1; i <= n; ++i) ret = ret.multiply(BigInteger.valueOf(i));
        return ret;
    }
}

5 加入缓存机制

public class FactorialUtil{
    static HashMap<Integer,BigInteger> cache = new HashMap<Integer,BigInteger>();
    
    public static BigInteger factorial(int n){
        BigInteger ret;
    
        if (n == 0) return BigInteger.ONE;
        if (null != (ret = cache.get(n))) return ret;
        ret = BigInteger.valueOf(n).multiply(factorial(n-1));
        cache.put(n, ret);
        return ret;
    }
}

6 使用接口编程,把算法实现推向实现,即使用了策略模式

工具类:

public class FactorialUtil{
    private static FactorialUtil singleton;
    private FactorialAlgorithm algorithm;

    /**
     * Default (internal) constructor constructs our default algorithm.
     */
    private FactorialUtil()
    {
        algorithm = new CachedFactorialImplementation();
    }

    /**
     * New initializer which allows selection of the algorithm mechanism
     * @param algorithm
     */
    public FactorialUtil(FactorialAlgorithm a)
    {
        algorithm = a;
    }

    /**
     * Default public interface for handling our factorial algorithm. Uses
     * the old standard established earlier for calling into our utility class.
     * @param n
     * @return
     */
    public static BigInteger factorial(int n)
    {
        if (singleton == null) {
            // Use default constructor which uses default algorithm
            singleton = new FactorialUtil();
        }
        return singleton.doFactorial(n);
    }

    /**
     * New mechanism which allows us to instantiate individual factorial
     * utilitiy classes and invoke customized factorial algorithms directory.
     * @param n
     * @return
     */
    private BigInteger doFactorial(int n)
    {
        // Defer to our algorithm
        return algorithm.factorial(n);
    }
}

接口:

public interface FactorialAlgorithm{
    BigInteger factorial(int n);
}

缓存实现

public class CachedFactorialImplementation implements FactorialAlgorithm
{
    static HashMap<Integer,BigInteger> cache = new HashMap<Integer,BigInteger>();

    @Override
    public BigInteger factorial(int n)
    {
        BigInteger ret;

        if (n == 0) return BigInteger.ONE;
        if (null != (ret = cache.get(n))) return ret;
        ret = BigInteger.valueOf(n).multiply(factorial(n-1));
        cache.put(n, ret);
        return ret;
    }
}

循环实现

public class LoopedFactorialImplementation implements FactorialAlgorithm
{
    @Override
    public BigInteger factorial(int n)
    {
        BigInteger ret = BigInteger.ONE;
        for (int i = 1; i <= n; ++i) ret = ret.multiply(BigInteger.valueOf(i));
        return ret;
    }
}

这种方式无法实现运行时动态选择使用哪个实现类。即,无法完成如下的调用。

7 如何实现这种方式的动态调用?

public static void main(String[] args){
    System.getProperties().setProperty("com.chaosinmotion.factorialalgorithm", "cachedAlgorithm");//指定实现方式为cachedAlgorithm
    System.out.println("5! = " + FactorialUtil.factorial(5));//系统会使用了cachedAlgorithm方式
}

7.1 用map存储类映射

/**
 * Factory class manages the factorial algorithms in our system.
 * @author wwoody
 *
 */
public class FactorialAlgorithmFactory{//阶乘算法工厂
    private static HashMap<String,FactorialAlgorithm> mapping = new HashMap<String,FactorialAlgorithm>();
    private static HashMap<String,Class<? extends FactorialAlgorithm>> classMapping = new HashMap<String,Class<? extends FactorialAlgorithm>>();
    private static FactorialAlgorithm defaultAlgorithm = new CachedFactorialImplementation();

    /** Static initializer registers some of my known classes */
    static {
        try {
            Class.forName("com.chaosinmotion.factorial.LoopedFactorialImplementation");//这个类被注册进了classMapping
            Class.forName("com.chaosinmotion.factorial.CachedFactorialImplementation");//这个类被注册进了classMapping
        }
        catch (ClassNotFoundException e) {
            // Should never happen.
        }
    }

    /** Get the default algorithm for computing factorials */
    public static FactorialAlgorithm getDefaultAlgorithm()
    {
        if (defaultAlgorithm == null) {
            // Warning: this will fail if for whatever reason CachedFactorialImplementation
            // is not in the class path.
            defaultAlgorithm = getAlgorithm("cachedAlgorithm");
        }
        return defaultAlgorithm;
    }

    /** Get the factorial algorithm specified by name */
    public static FactorialAlgorithm getAlgorithm(String name)
    {
        FactorialAlgorithm f = mapping.get(name);
        if (f == null) {
            // We haven't created an instance yet. Get it from the class mapping.
            Class<? extends FactorialAlgorithm> c = classMapping.get(name);
            if (c != null) {
                // Create a new instance of the factorial algorithm specified
                try {
                    f = c.newInstance();
                    mapping.put(name, f);
                    return f;
                }
                catch (Exception e) {
                    // Log the error
                    Logger.getLogger("com.chaosinmotion.factorial").
                        warning("Unable to instantiate algorithm " +
                                c.getCanonicalName() + ", named " + name);
                }
            }
            return getDefaultAlgorithm(); // return something.
        }
        else return f;
    }

    /** Register the class so we can construct a new instance if not already initialized */
    public static void registerAlgorithm(String name, Class<? extends FactorialAlgorithm> f)
    {
        classMapping.put(name, f);
    }
}

7.2 重写阶乘工具类

public class FactorialUtil{
    private static FactorialUtil singleton;
    private FactorialAlgorithm algorithm;

    /**
     * Default (internal) constructor constructs our default algorithm.
     */
    private FactorialUtil()
    {
        String name = System.getProperty("com.chaosinmotion.factorialalgorithm", "cachedAlgorithm");
        if (name == null) {
            algorithm = FactorialAlgorithmFactory.getDefaultAlgorithm();
        } else {
            algorithm = FactorialAlgorithmFactory.getAlgorithm(name);
        }
    }

    /**
     * New initializer which allows selection of the algorithm mechanism
     * @param algorithm
     */
    public FactorialUtil(FactorialAlgorithm a)
    {
        algorithm = a;
    }

    /**
     * Utility to create by name. Calls into FactorialAlgorithmFactory to
     * actually get the algorithm.
     * @param name
     */
    public FactorialUtil(String name)
    {
        algorithm = FactorialAlgorithmFactory.getAlgorithm(name);
    }

    /**
     * Default public interface for handling our factorial algorithm. Uses
     * the old standard established earlier for calling into our utility class.
     * @param n
     * @return
     */
    public static BigInteger factorial(int n)
    {
        if (singleton == null) {
            // Use default constructor which uses default algorithm
            singleton = new FactorialUtil();
        }
        return singleton.doFactorial(n);
    }

    /**
     * New mechanism which allows us to instantiate individual factorial
     * utilitiy classes and invoke customized factorial algorithms directory.
     * @param n
     * @return
     */
    private BigInteger doFactorial(int n)
    {
        // Defer to our algorithm
        return algorithm.factorial(n);
    }
}

7.3 缓存实现

public class CachedFactorialImplementation implements FactorialAlgorithm
{
    static HashMap<Integer,BigInteger> cache = new HashMap<Integer,BigInteger>();

    static {
        FactorialAlgorithmFactory.registerAlgorithm("cachedAlgorithm", CachedFactorialImplementation.class);//被注册进classMapping
    }

    @Override
    public BigInteger factorial(int n)
    {
        BigInteger ret;

        if (null != (ret = cache.get(n))) return ret;
        ret = BigInteger.valueOf(n).multiply(factorial(n-1));
        cache.put(n, ret);
        return ret;
    }
}

7.4 迭代实现

public class LoopedFactorialImplementation implements FactorialAlgorithm
{
    static {
        FactorialAlgorithmFactory.registerAlgorithm("loopedAlgorithm", LoopedFactorialImplementation.class);//被注册进classMapping
    }
    @Override
    public BigInteger factorial(int n)
    {
        BigInteger ret = BigInteger.ONE;
        for (int i = 1; i <= n; ++i) ret = ret.multiply(BigInteger.valueOf(i));
        return ret;
    }
}

7.5 递归实现

public class RecursiveFactorialImplementation implements FactorialAlgorithm
{
    static {
        FactorialAlgorithmFactory.registerAlgorithm("recursiveAlgorithm", RecursiveFactorialImplementation.class);
    }

    @Override
    public BigInteger factorial(int n)
    {
        if (n == 0) return BigInteger.ONE;
        return BigInteger.valueOf(n).multiply(factorial(n-1));
    }
}

7.6 调用例子

public static void main(String[] args){
    try {
        Class.forName("com.chaosinmotion.factorial.RecursiveFactorialImplementation");
    }
    catch (ClassNotFoundException e) {
        // if this fails, no matter; we'll still use the default implementation.
    }
    System.getProperties().setProperty("com.chaosinmotion.factorialalgorithm", "recursiveAlgorithm");
    System.out.println("5! = " + FactorialUtil.factorial(5));
}

7.7 总结

程序员想要使用自己的实现类来完成阶乘运算,只需要

  1. 写一个实现了 FactorialAlgorithm 接口的类
  2. 在这个类的装载过程里里完成对自己的注册
  3. 使用
    1. 装载自己的实现类 Class.forName(…);
    2. 设置系统属性,供程序从classMap中查找自己的实现类。

8 应用

JDBC Driver 的实现,就是类似方式:

Class.forName("org.gjt.mm.mysql.Driver");
Connection con = DriverManager.getConnection(url,?myLogin", "myPassword");

实际上jdbc driver有一个静态初始化

static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can't register driver!");
    }
}

参考: http://chaosinmotion.com/blog/?p=622

 http://en.wikipedia.org/wiki/Strategy_pattern

Dapple Hou

 mmonkeyer@163.com

0
0
分享到:
评论

相关推荐

    实现阶乘功能JAVA小程序

    一个实现阶乘功能的JAVA小程序,代码较为简单。

    C#大数阶乘源程序 C#大数阶乘源程序

    本项目名为"C#大数阶乘源程序",其目标是实现一个能够计算10001以下整数阶乘的程序,并且理论上可以扩展到处理无限大的数字。下面将详细介绍这个项目中的关键知识点。 首先,我们来看`System.Numerics.BigInteger`...

    java阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘

    java阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘阶乘

    阶乘算法 阶乘问题 C# 小程序

    在C#中,我们可以采用递归或循环两种主要方法来编写阶乘算法的小程序。下面分别介绍这两种方法: 1. **递归方法**: 递归是解决问题的一种自我调用的策略。对于阶乘问题,递归函数可以这样定义:n! = n * (n-1)!。...

    求阶乘-c#编写的求阶乘的程序

    在这个版本中,我们初始化`result`为1,然后通过一个for循环,从1累乘到输入的数字,最终得到阶乘结果。 通过实践这样的程序,初学者可以学习到C#的基本语法,包括变量声明、输入输出、函数定义以及递归和循环两种...

    python算阶乘小程序

    python算阶乘小程序 python算阶乘小程序

    n的阶乘 C++实现

    n的阶乘 C++实现

    计组课程设计阶乘

    ### 计算机组成原理课程设计——微程序实现阶乘 #### 一、程序设计目的与基本原理 ##### 1. 程序设计目的 本课程设计的主要目的是让学生通过实践,更深入地理解计算机组成的原理及其应用。具体目标包括: - **...

    汇编 子程序设计 阶乘

    在本实验报告中,重点讨论了如何利用递归子程序来计算阶乘,这是一种高效的算法设计方法。递归子程序是指在执行过程中会调用自身的子程序,这种调用方式在处理某些特定问题时特别有效,如计算阶乘。 阶乘是一个数学...

    用于求阶乘的c语言程序

    C语言阶乘程序的实现与优化 在计算机科学中,阶乘是一个基本的数学概念,对于大多数程序员来说,实现一个阶乘函数是一个基本的编程任务。然而,在实际应用中,我们经常需要处理大规模的阶乘运算,这就需要我们开发...

    ARM汇编语言程序设计实例解析-阶乘操作

    "ARM汇编语言程序设计实例解析-阶乘操作" ...ARM汇编语言程序设计-阶乘操作是一个非常重要的知识点,通过这个实例,我们可以了解ARM汇编语言程序设计的思想、流程和实现方法,并且可以应用于各种领域。

    大数阶乘用C++语言实现

    本文介绍的程序通过使用一个动态调整大小的数组来存储大数的每一位,从而实现了对任意大小数字的阶乘计算。具体步骤如下: 1. **初始化数组**:创建一个足够大的数组 `a[]` 来存放结果,并将数组的第一位初始化为1...

    阶乘算法的简单实现

    阶乘算法是计算机科学中一个基础且重要的概念,主要用于数学计算和组合数学中。阶乘表示的是一个正整数n的...无论是C#还是JavaScript,理解并实现阶乘算法是学习编程基础的重要一步,也是进一步学习更复杂算法的基础。

    java阶乘应用小程序

    在这个小程序中,我们将探讨如何使用JAVA来计算一个整数的阶乘,并进一步实现1到20所有整数阶乘的和。下面我们将深入讲解相关知识点。 首先,让我们了解什么是阶乘。阶乘是一个正整数n与小于它的所有正整数的乘积,...

    C++ 阶乘算法实现代码

    C++ 阶乘算法实现代码,用C++编写的简单阶乘计算程序。

    java递归实现 阶乘

    在这个实例中,我们将深入探讨如何使用Java递归实现阶乘计算,并以1到10的数字为例进行演示。 阶乘是一个数学概念,表示一个正整数n的所有小于等于n的正整数的乘积,通常表示为n!。例如,5的阶乘(5!)是5 × 4 × ...

    大数阶乘程序(VS2005实现)

    本项目“大数阶乘程序(VS2005实现)”提供了一个简单的解决方案,采用数组来存储和处理大数。在本文中,我们将深入探讨大数阶乘的算法、数组在大数表示中的应用以及如何在Visual Studio 2005环境下进行开发。 首先...

    vc++数组实现大数阶乘

    2. 对于输入的正整数n,从1到n遍历,每次迭代将当前数与当前阶乘结果相乘,并更新数组中的值。这涉及到大数乘法算法,例如Karatsuba乘法或者Toom-Cook乘法,这些算法可以高效地处理大数乘法。 3. 在乘法过程中,需要...

    用汇编写的10!阶乘

    ### 汇编语言实现10的阶乘 在计算机科学与编程领域中,阶乘是一种常见的数学运算,表示为n!,定义为所有小于等于n的正整数的乘积。例如,5! = 5 × 4 × 3 × 2 × 1 = 120。本文将详细介绍如何使用8086汇编语言...

    C++实现阶乘运算 简单小程序

    输入 计算阶乘的数 得到结果 很简单的小程序

Global site tag (gtag.js) - Google Analytics