Groovy与JAVA实现Visitor模式的对比
| 本篇文章旨在突出Groovy的闭包和动态类型特性,所以建议阅读前有相关知识结构。 设计模式与JAVA的默契程度不可小视,但部分模式使用Groovy的闭包和动态类型特性来实现更显得轻巧与灵活。 下面使用JAVA和Groovy分别实现Visitor模式,并分析两者的优劣: 首先是Visitor模式的定义及使用场景: GoF对访问者模式定义为:表示一个作用于某对象结构中各元素的操作。它可以使你不修改各元素类的前提下定义作用于这些元素的新操作,也就是动态的增加新的方法。 例子很简单,以图形类基础,扩展不同图形,并实现各种图形的面积计算方法。使用Visitor模式将不同图形集合类实现不同的商业逻辑行为。 JAVA实现: import java.util.ArrayList;
import java.util.List;
//绘制图形类
public class Drawing {
	//图形集合
	List<Shape> shapes = new ArrayList<Shape>();
	//留给客户端调用的方法
	public void accept(Visitor v){
		for(Shape shape : shapes){
			shape.accept(v);
		}
	}
	//添加图形
	public void addShape(Shape shape){
		shapes.add(shape);
	}
	//删除图形
	public void removeShape(Shape shape){
		shapes.remove(shape);
	}
	//Main方法
	public static void main(String[] args){
		Drawing draw = new Drawing();
		draw.addShape(new Square(1));
		draw.addShape(new Circle(1));
		//VisitorA的商业逻辑
		VisitorA visitorA = new VisitorA();//←
		draw.accept(visitorA);
		System.out.println("VisitorA : Total : " + visitorA.getTotalArea());//←
		//VisitorB的商业逻辑
		Visitor visitorB = new VisitorB();
		draw.accept(visitorB);
	}
}
//Visitor模式接口
interface Visitor{
	public void visit(Shape shape);
}
//Visitor的一个实现类:用于计算图形集合的面积综合
class VisitorA implements Visitor {
	double totalArea;//←
	public double getTotalArea() {
		return totalArea;
	}
	@Override
	public void visit(Shape shape) {
		totalArea += shape.area();
	}
}
//Visitor的另一个实现类:用于输出图形集合中每个图形的面积
class VisitorB implements Visitor {
	@Override
	public void visit(Shape shape) {
		System.out.println("VisitorB : " + shape.getClass().getName() + " : " +  shape.area());
	}
}
//图形父类
abstract class  Shape {
	public void accept(Visitor v){ v.visit(this);}
	//面积计算方法
	public abstract double area();
}
//正方形
class Square extends Shape {
	double width;
	Square(double width){
		this.width = width;
	}
	public double area(){
		return Math.pow(width,2);
	}
}
//圆形
class Circle extends Shape {
	double radius;
	Circle(double radius){
		this.radius = radius;
	}
	public double area(){
		return Math.PI * Math.pow(radius,2);
	}
}输出: VisitorA : Total : 4.141592653589793 Groovy实现: //绘制图形类
class Drawing {
	//图形集合
	def List shapes
	//留给客户端调用的方法,参数为闭包类型
	def accept(Closure yield) { shapes.each {it.accept(yield)}}//利用Collection的each方法,使用闭包循环调用集合内图形
	//Main方法
	static void main(args) {
		//构造方法都可以在运行时生成,果然是动态语言
		def picture = new Drawing(shapes : [new Square(width:1),new Circle(radius:1)])
		def total = 0
		//使用闭包计算图形集合的面积综合
		picture.accept {total += it.area()}//←
		println "VisitorA : Total : $total"
		//使用闭包输出图形集合中每个图形的面积
		picture.accept {println "VisitorB : ${it.class.getName()} : ${it.area()}"}
	}
}
//图形父类
class Shape {
	def accept(Closure yield) { yield(this) }//有是闭包
}
//正方形
class Square extends Shape {
	def width
	def area() { width ** 2 }
}
//圆形
class Circle extends Shape {
	def radius
	def area() { Math.PI * radius ** 2}
}输出: VisitorA : Total : 4.141592653589793 分析: 1.先不用深入看代码,单从代码行数上来看Groovy就有明显的优势,5:2的比例,生产效率远大于JAVA。 2.请注意被【←】标注的代码行,有没有看出什么问题。是的,Groovy的闭包可以轻松使用被调用者的局部变量;而JAVA呢,为使Visitor实现类内的属性暴露给被调用者,不得不用丑陋的VisitorA visitorA = new VisitorA()来声明而破坏了接口的统一性。 3.代码中Groovy的动态生成构造函数等很多特性也显示了它就是为敏捷而生的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! | 
