分类: C/C++
2012-03-25 18:34:16
Replace Conditional with Visitor 用Visitor代替条件语句: 如果你有一个很大的条件语句块,每个分支对应着不同行为。Replace Conditional with Polymorphism可以解决这个问题。但是如果这样的行为会常改变,比如每个分支都是一类人吃饭。于是有几个类:老板,打工的,要饭的。每个类各自 实现“吃饭”方法。但一旦说,我们不吃饭了,我们改成喝汤。每个子类都要把“吃饭”这个方法改为“喝汤”。如果有几十个子类,就哭了。Visitor就可 以适应这种变化。每个类都有一个方法,不是吃饭,也不是喝汤,就叫“接受访问”(accept)。我们先建一个
class Visiotr {
void visitManager(Manager);
void visitEngineer(Engineer);
}
如此,就一个父类
class Person {
abstract void accept(Visitor);
}
class Manager : Person {
void accept(Vistor v) { v.visitManager(this); }
}
class Engineer : Person {
void accept(Visitor v) {v.visitEngineer(this); }
}
这样呢, 这种Visitor模式可以这样使用:
void f(Person p) { p.accept(new EatRiceVisitor); }
如果不想吃饭了,变为喝汤,只要换一个Visitor
void f(Person p) { p.accept(new DrinkSoapVisitor); }
Visitor的好处就是需要改变行为时,只在Visitor这一个类里修改。并且可以通过加入其它Visitor的方式扩展行为。
Convert Dynamic to Static Construction 将动态构造转换为静态构造: 动态构造就是运行时确定对象的类型,比如Java里的Class.forName("MyClass").newInstance();这样的好处是很灵 活,坏处就是跳过了编译时的检测,而且容易造成运行时异常。如果灵活性不是你追求的,还是老老实实的静态构造:MyClass object = new MyClass。
Convert Static to Dynamic Construction 将静态构造转换为动态构造:如果对象的类型确实不能在编译时确定,那就用动态构造吧。
Extract Package 提取包:一堆为了同一目的而存在的类,可以整合成一个包。
Move Class 移动类:如果一个类不属于一个包,把它移到它该属于的包里。
Reduce Scope of Variable 缩小变量的作用域:如 果一个变量只在某个作用域里用到,就不用在更大的作用域去声明它。如果if (bCondition) { int a = 0; b = a * 5; } 可以解决问题,就不必写成 int a = 0; if (bCondition) { b = a*5; } 控制作用域可以防止变量被声明却没有被用,而且如果bCondition是false的话,可以减少一次不必要的初始化(如果是变量是对象初始化就更 费资源了);还有好处就是你可以在别的作用域声明一个同样名字的变量,而不必担心干扰已经的变量。
Remove Double Negative 去除双重否定:不要太相信自己和同事的智商,也不要特意去杀死别人的脑细胞。if (!isNotFound())这样的东西写出来,可能会浪费别人四分之一柱香的时间去反应。写成 if(isFound())就好了。
Replace Assignment with Initialization 用初始化代替赋值:int a; ...; a = 7;写成int a = 7; 可读性提高,而且不会不小心使用了一个未初始化的变量。
Replace Iteration with Recursion 用递归代替迭代:主要还是看程序可读性,如果迭代的代码让人很难看懂它要做什么,可以考虑用递归函数,毕竟函数还能有个名字。
Replace Recursion with Iteration 用迭代代替递归: 递归一般用来处理复杂的重复。如果为了求一个整数的阶而用递归,你就被鄙视了。递归会增加栈的大小,增加函数调用的开销,所以要慎用。有一种递归要做 tail recursion,就是递归函数在函数末尾调用下一个递归. f() { ......; f(); } 这种递归被认为是没有意义的,应该用迭代来代替。因为递归的精髓在于当前的变量放在栈中,在下一递归返回后,可以从栈中返回变量,继续上一次未完成的递 归。没有用到这种特性的变量就是无意义的,如tail recursion。
Replace Static Variable with Parameter 用参数代替静态变量: 有时函数里会使用一些静态变量写死,如果发现这个静态变量可能根据需要外在环境改变时,可以把它作为函数的一个参数传进来。void Print () { std::cout << "hello"; } => void Print(ostream) { ostream << "hello"; } 这样它不仅可以支持cout,也可以接受一个sstream.
Reverse Conditional 将条件取反:if-else块里,条件放if里还是else的顺序很关键。if (!isEnabled()) ... else... 可以写成 if (isEnabled()) ... else ... 这样可以减轻脑力负担。
Split Loop 分离循环语句:for (int i = 0; i < n; ++i) { Total(i); Average(i); } 应该把它分成两个循环 for(..) Total(i); for(...) Average(i); 是不是有点难接受?我一开始也觉得少一次循环不挺好的吗?不过拆分这个循环是有原因的。拆分后程序可读性提高,之后甚至可以用两个函数代替这两个循环。而 且现在程序performance的瓶颈基本不会是这些迭代造成的。可读性还是要放在第一位。