上次写了公英制重量单位换算工具,这次添加了长度单位换算。直达链接:

实用计算器

现在晚上要照顾大喵,睡眠很不规律,所以早上必须定闹钟。而大喵就睡我旁边,闹钟响的时候很容易也吵醒她。刚好看到小米手环的震动闹铃功能,正好能解决这个问题。于是果断天猫入手,趁帮一个朋友买东西,搭包裹寄过来。

老实说,看外观和做工,79块rmb的价钱还是很公道的:

前段时间诸多不顺,没太多精力打理博客。现在总算都尘埃落定了,还是要静下心来把很多事情坚持下去。

因为我好像查一万次都记不住英制和公制单位的换算,干脆自己写个工具,最起码不用每次查都绕道google。目前只有重量单位,慢慢添加其它。

实用计算器

还是用的AngularJS,这次相对前面写的两个小东西,稍有了点复杂度:多个输入/输出框要检测唯一输入。一开始用的$watch,貌似不太好用,主要是无法区分用户输入和计算结果变化,最后导致重复计算。查了好久才发现ng-change属性能避免这一点。

另外推荐一本Angular的书:AngularJS - Brad Green & Shyam Seshadri - O'Reilly

使用函数对象来定义运行策略

有些语言支持函数指针,代理(delegate),lambda表达式,或者其它类似的机制来存储和传递可执行的"函数"。这些特性允许程序在运行时动态改变行为,而这样的设计被称为"策略"模式(strategy pattern)。比如在c语言标准库中,qsort函数有一个参数是指向comparator函数的函数指针,这个comparator在排序过程中被用来对序列中的两个元素进行比较,通过传递不同的comparator函数,qsort可以动态采用不同的排序(比较)策略,而这个被传入的comparator就可以称为一个排序策略。

Java不支持函数指针,但通过对象引用可以实现类似的功能。通常说来,调用一个对象的方法,是要对这个对象本身进行操作。但如果一个方法接受的参数是指向其它对象的引用,那么这个方法也可以对这些传入的对象进行操作。如果一个类仅开放一个这样(对其他对象进行操作)的方法,那么它的对象就等同于一个指向该方法的函数指针,而这样的对象被称为函数对象。比如下面的类:

class StringLengthComparator {

	public int compare(String s1, String s2) {
		return s1.length() - s2.length();
	}
}

继承优于标签类型

开发者有时会遇到这样的类:其对象有多种不同"类别",每一"类别"的对象都用一个特定的标签来识别。比如下面的类,可以代表"圆圈"或"矩形":

// Tagged class - vastly inferior to a class hierarchy!
class Figure {
	enum Shape { RECTANGLE, CIRCLE };
	
	// Tag field - the shape of this figure
	final Shape shape;
	
	// These fields are used only if shape is RECTANGLE
	double length;
	double width;
	
	// This field is used only if shape is CIRCLE
	double radius;
	
	// Constructor for circle
	Figure(double radius) {
		shape = Shape.CIRCLE;
		this.radius = radius;
	}
	
	// Constructor for rectangle
	Figure(double length, double width) {
		shape = Shape.RECTANGLE;
		this.length = length;
		this.width = width;
	}
	
	double area() {
		switch(shape) {
			case RECTANGLE:
				return length * width;
			case CIRCLE:
				return Math.PI * (radius * radius);
			default:
				throw new AssertionError();
		}
	}
}

接口只用来定义类型

如果一个类实现了某个接口,那么这个接口类型可以成为指向该类对象的引用。因此类与接口之间的"实现"关系,应该能使用户通过接口了解对象的行为。除了这个场景以外,定义接口都是不合适的。违背上述原则的一个反例是常量接口,这样的接口不定义任何方法,仅含有静态final属性,每一个属性都被开放为常量。用户类通过实现这些接口来避免使用常量全名。比如下面的例子:

// Constant interface antipattern - do not use!
public interface PhysicalConstants {
	// Avogadro's number (1/mol)
	static final double AVOGADROS_NUMBER = 6.02214199e23;
	// Boltzmann constant (J/K)
	static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
	// Mass of the electron (kg)
	static final double ELECTRON_MASS = 9.10938188e-31;
}

第2页 共10页