本篇文章旨在突出Groovy的闭包和动态类型特性,所以建议阅读前有相关知识结构。
设计模式与JAVA的默契程度不可小视,但部分模式使用Groovy的闭包和动态类型特性来实现更显得轻巧与灵活。
下面使用JAVA和Groovy分别实现Visitor模式,并分析两者的优劣:
首先是Visitor模式的定义及使用场景:
GoF对访问者模式定义为:表示一个作用于某对象结构中各元素的 *** 作。它可以使你不修改各元素类的前提下定义作用于这些元素的新 *** 作,也就是动态的增加新的方法。
Visitor模式是一种分离对象数据结构与行为的方法,通过这种分离,可以为一个已存在的类或类群增加新的 *** 作而无需为它们作任何修改。
Visitor模式的优点:
- 分离对象的数据结构与行为,让不同的类完成不同的功能
- 可以不修改已有类的基础上增加新的 *** 作行为
- 从另一个角度来看,同一个数据结构,为其实现不同的观察者,便可呈现不同的行为
例子很简单,以图形类基础,扩展不同图形,并实现各种图形的面积计算方法。使用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
VisitorB : Square : 1.0
VisitorB : Circle : 3.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
VisitorB : Square : 1
VisitorB : Circle : 3.141592653589793
分析:
1.先不用深入看代码,单从代码行数上来看Groovy就有明显的优势,5:2的比例,生产效率远大于JAVA。
2.请注意被【←】标注的代码行,有没有看出什么问题。是的,Groovy的闭包可以轻松使用被调用者的局部变量;而JAVA呢,为使Visitor实现类内的属性暴露给被调用者,不得不用丑陋的VisitorA visitorA = new VisitorA()来声明而破坏了接口的统一性。
3.代码中Groovy的动态生成构造函数等很多特性也显示了它就是为敏捷而生的。
总结以上是内存溢出为你收集整理的Groovy与JAVA实现Visitor模式的对比全部内容,希望文章能够帮你解决Groovy与JAVA实现Visitor模式的对比所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)