<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      奔跑的肥豬

      導(dǎo)航

      Visitor 模式心得

      最近讀到Visitor模式,還是一知半解的。偶然翻到Uncle Bob對(duì)該模式的推導(dǎo)過(guò)程,有所心得,和大家分享一下。 Uncle Bob 的鏈接是: http://butunclebob.com/ArticleS.UncleBob.VisitorVersusInstanceOf。個(gè)人覺(jué)得該模式用來(lái)操作復(fù)雜對(duì)象集合,特別適用于報(bào)表生成。因?yàn)閳?bào)表的來(lái)源相對(duì)穩(wěn)定(復(fù)雜數(shù)據(jù)集合),但是表現(xiàn)形式卻是千變?nèi)f化。言歸正傳,我將該博客的內(nèi)容按照自己的理解分享出來(lái),如果有什么不對(duì)的地方,請(qǐng)指正。

      首先有一個(gè)如下簡(jiǎn)單的場(chǎng)景,Bob先生的公司提供計(jì)算機(jī)方面的培訓(xùn)服務(wù),對(duì)社會(huì)人士開(kāi)設(shè)二門(mén)課程,一門(mén)是OOD, 一門(mén)是Java,java課程需要上機(jī)(結(jié)對(duì)編程,所以二個(gè)人用一臺(tái)機(jī)器),所以需要根據(jù)報(bào)名的時(shí)間計(jì)算具體的機(jī)器數(shù)目:

      public abstract class Course {
      
          protected GregorianCalendar startDate;
          protected int students;
      
          public Course(GregorianCalendar startDate, int students) {
              this.startDate = (GregorianCalendar) startDate.clone();
              this.students = students;
          }
      
          abstract public int getComputersInUse(GregorianCalendar date);
      }
      View Code
      public class AOODCourse extends Course {
      
          public AOODCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
          }
      
          public int getComputersInUse(GregorianCalendar date) {
              return 0;
          }
      }
      View Code
      public class JavaCourse extends Course {
      
          private GregorianCalendar endDate;
      
          public JavaCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
              endDate = (GregorianCalendar) startDate.clone();
              endDate.add(Calendar.DAY_OF_WEEK, 4);
          }
      
          public int getComputersInUse(GregorianCalendar date) {
              int resources = 0;
              if (!date.before(startDate) && !date.after(endDate)) {
                  resources = Math.round(students/2);
              }
              return resources;
          }
      }
      View Code

      代碼實(shí)現(xiàn)了,B先生很happy。不久客戶(hù)說(shuō)需要生一份報(bào)表,B先生想了5分鐘,洋洋灑灑寫(xiě)下如下代碼:

       

      public abstract class Course {
      
          protected GregorianCalendar startDate;
          protected int students;
          protected SimpleDateFormat dateFormat;
      
          public Course(GregorianCalendar startDate, int students) {
              this.startDate = (GregorianCalendar) startDate.clone();
              this.students = students;
              this.dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public String generateComputerReportLine() {
              StringBuffer line = new StringBuffer();
              line.append(dateFormat.format(startDate.getTime())).append(" ")
                      .append(courseName()).append(" ")
                      .append(computersInUse()).append(" Computers\n");
              return line.toString();
          }
      
          public GregorianCalendar getStartDate() {
              return startDate;
          }
      
          protected abstract String courseName();
          protected abstract String computersInUse();
      }
      View Code
      public class AOODCourse extends Course {
      
          public AOODCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
          }
      
          @Override
          protected String courseName() {
              return "AOOD";
          }
      
          @Override
          protected String computersInUse() {
              return "0";
          }
      }
      View Code
      public class JavaCourse extends Course {
      
          private GregorianCalendar endDate;
      
          public JavaCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
              endDate = (GregorianCalendar) startDate.clone();
              endDate.add(Calendar.DAY_OF_WEEK, 4);
          }
      
          @Override
          protected String courseName() {
              return "Java";
          }
      
          @Override
          protected String computersInUse() {
              return String.valueOf(Math.round(students/2));
          }
      }
      View Code
      public class CourseResourceTracker<T extends Course> {
      
          Set<T> courses = new HashSet<>();
      
          public String generateReport() {
              StringBuilder reports = new StringBuilder();
              for (Iterator i = courses.iterator(); i.hasNext();) {
                  T course = (T) i.next();
                  reports.append(course.generateComputerReportLine()) ;
              }
              return reports.toString();
          }
      
          public void add(T course) {
              if (course == null) return;
      
              courses.add(course);
          }
      
          public void remove(T course) {
              if (course == null) return;
      
              courses.remove(course);
          }
      
          public static void main(String[] param) {
              CourseResourceTracker tracker = new CourseResourceTracker();
              tracker.add(new AOODCourse(new GregorianCalendar(2015, 3, 20), 10));
              tracker.add(new JavaCourse(new GregorianCalendar(2015, 3, 20), 10));
              System.out.println("Report is : " + tracker.generateReport());
          }
      }
      View Code

      報(bào)表很簡(jiǎn)單, 打印結(jié)果如下, 格式為: 時(shí)間 + 名稱(chēng) + 數(shù)量

      Report is : 04/20/2015 AOOD 0 Computers
      04/20/2015 Java 5 Computers

      B洋洋得意,客戶(hù)又來(lái)了新的需求,前面的報(bào)表太簡(jiǎn)單了,需要針對(duì)不同的課程打印不同的內(nèi)容:

       

      public abstract class Course {
      
          protected GregorianCalendar startDate;
          protected int students;
          protected SimpleDateFormat dateFormat;
      
          public Course(GregorianCalendar startDate, int students) {
              this.startDate = (GregorianCalendar) startDate.clone();
              this.students = students;
              this.dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public GregorianCalendar getStartDate() {
              return startDate;
          }
      
          abstract public int getComputersInUse(GregorianCalendar date);
      }
      View Code
      public class AOODCourse extends Course {
      
          public AOODCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
          }
      
          public int getComputersInUse(GregorianCalendar date) {
              return 0;
          }
      }
      View Code
      public class JavaCourse extends Course {
      
          private GregorianCalendar endDate;
      
          public JavaCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
              endDate = (GregorianCalendar) startDate.clone();
              endDate.add(Calendar.DAY_OF_WEEK, 4);
          }
      
          public int getComputersInUse(GregorianCalendar date) {
              int resources = 0;
              if (!date.before(startDate) && !date.after(endDate)) {
                  resources = Math.round(students/2);
              }
              return resources;
          }
      
          public int getTotalComputers() {
              return students/2;
          }
      }
      View Code
      public class CourseComputerReport {
          protected SimpleDateFormat dateFormat;
      
          public CourseComputerReport() {
              dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public String generateComputerReport(List courses) {
              if (courses == null || courses.size() == 0) return null;
      
              StringBuffer report = new StringBuffer();
              for (Iterator i = courses.iterator(); i.hasNext();) {
                  Course course = (Course) i.next();
                  report.append(dateFormat.format(course.getStartDate().getTime())).append(" ");
                  if (course instanceof AOODCourse) {
                      report.append("AOOD 0 Computers\n");
                  } else if (course instanceof JavaCourse) {
                      report.append("Java ");
                      JavaCourse jc = (JavaCourse)course;
                      report.append(String.valueOf(jc.getTotalComputers())).append(" Computers\n");
                  }
              }
              return report.toString();
          }
      
          public static void main(String[] param) {
              CourseComputerReport report = new CourseComputerReport();
              List<Course> courses = new ArrayList<>();
              courses.add(new AOODCourse(new GregorianCalendar(2015, 3, 20), 10));
              courses.add(new JavaCourse(new GregorianCalendar(2015, 3, 20), 10));
              System.out.println("Report is : " + report.generateComputerReport(courses));
          }
      }
      View Code

      從上面的UML 類(lèi)圖可以看出,CourseComputerReport 因?yàn)閷?duì)每門(mén)課程的format不一致,需要遍歷的時(shí)候針對(duì)不同的課程設(shè)置不同的格式從而導(dǎo)致CourseReport和Course之前出現(xiàn)強(qiáng)耦合, 可以通過(guò)重構(gòu)方法 generateComputerReport 使之更加合理:

      public abstract class CourseReport {
          protected SimpleDateFormat dateFormat;
      
          public CourseReport() {
              dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public String generateComputerReport(List courses) {
              StringBuffer report = new StringBuffer();
              for (Iterator i = courses.iterator(); i.hasNext();) {
                  Course course = (Course) i.next();
                  report.append(dateFormat.format(course.getStartDate().getTime())).append(" ");
                  if (course instanceof AOODCourse) {
                      appendAOODLine((AOODCourse)course, report);
                  } else if (course instanceof JavaCourse) {
                      appendJavaLine((JavaCourse) course, report);
                  }
              }
              return report.toString();
          }
      
          protected abstract void appendJavaLine(JavaCourse course, StringBuffer report);
          protected abstract void appendAOODLine(AOODCourse course, StringBuffer report);
      }
      View Code
      public class CourseComputerReport extends CourseReport{
      
          protected void appendJavaLine(JavaCourse course, StringBuffer report) {
              report.append("Java ");
              report.append(String.valueOf(course.getTotalComputers())).append(" Computers\n");
          }
      
          protected void appendAOODLine(AOODCourse course, StringBuffer report) {
              report.append("AOOD 0 Computers\n");
          }
      
          public static void main(String[] param) {
              CourseComputerReport report = new CourseComputerReport();
              List<Course> courses = new ArrayList<>();
              courses.add(new AOODCourse(new GregorianCalendar(2015, 3, 20), 10));
              courses.add(new JavaCourse(new GregorianCalendar(2015, 3, 20), 10));
              System.out.println("Report is : " + report.generateComputerReport(courses));
          }
      }
      View Code

      老鳥(niǎo)L看了B的實(shí)現(xiàn)后,提出了自己的看法,為什么 CourseReport 需要依賴(lài)具體的Course, 能否將Course告訴reporter 而不是Reporter來(lái)判斷具體的Course。 并將Visitor的經(jīng)典類(lèi)圖隨手拋給小B:

      小B恍然大悟,修改代碼如下:

       

      public abstract class Course {
      
          protected GregorianCalendar startDate;
          protected int students;
          protected SimpleDateFormat dateFormat;
      
          public Course(GregorianCalendar startDate, int students) {
              this.startDate = (GregorianCalendar) startDate.clone();
              this.students = students;
              this.dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public GregorianCalendar getStartDate() {
              return startDate;
          }
      
          abstract void accept(CourseVisitor courseVisitor);
      View Code
      public class AOODCourse extends Course {
      
          public AOODCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
          }
      
          @Override
          void accept(CourseVisitor courseVisitor) {
              courseVisitor.visit(this);
          }
      }
      View Code
      public class JavaCourse extends Course {
      
          private GregorianCalendar endDate;
      
          public JavaCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
              endDate = (GregorianCalendar) startDate.clone();
              endDate.add(Calendar.DAY_OF_WEEK, 4);
          }
      
          @Override
          void accept(CourseVisitor courseVisitor) {
              courseVisitor.visit(this);
          }
      
          public int getTotalComputers() {
              return students/2;
          }
      }
      View Code
      public interface CourseVisitor {
          void visit(AOODCourse aoodCourse);
          void visit(JavaCourse javaCourse);
      }
      View Code
      public class ReportCourseVisitor implements CourseVisitor {
      
          protected StringBuffer report;
      
          public ReportCourseVisitor(StringBuffer report) {
              this.report = report;
      
          }
      
          @Override
          public void visit(AOODCourse aoodCourse) {
              report.append("AOOD 0 Computers\n");
          }
      
          @Override
          public void visit(JavaCourse javaCourse) {
              report.append("Java ");
              report.append(String.valueOf(javaCourse.getTotalComputers())).append(" Computers\n");
          }
      }
      View Code
      public abstract class CourseReport {
      
          protected SimpleDateFormat dateFormat;
      
          public CourseReport() {
              dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public String generateComputerReport(List courses) {
              StringBuffer report = new StringBuffer();
              CourseVisitor v = makeReportVisitor(report);
              for (Iterator i = courses.iterator(); i.hasNext();) {
                  Course course = (Course) i.next();
                  report.append(dateFormat.format(course.getStartDate().getTime())).append(" ");
                  course.accept(v);
              }
              return report.toString();
          }
      
          protected abstract CourseVisitor makeReportVisitor(StringBuffer report);
      }
      View Code
      public class CourseComputerReport extends CourseReport{
      
          public static void main(String[] param) {
              CourseComputerReport report = new CourseComputerReport();
              List<Course> courses = new ArrayList<>();
              courses.add(new AOODCourse(new GregorianCalendar(2015, 3, 20), 10));
              courses.add(new JavaCourse(new GregorianCalendar(2015, 3, 20), 10));
              System.out.println("Report is : " + report.generateComputerReport(courses));
          }
      
          @Override
          protected CourseVisitor makeReportVisitor(StringBuffer report) {
              return new ReportCourseVisitor(report);
          }
      }
      View Code

       老鳥(niǎo)L看了以后表示滿意,同時(shí)指出如果添加新的Course,由于所有的course都依賴(lài)CourseVisitor,而courseVisitor需要添加新的接口,所有的course需要重新打包和編譯。是否可以新建一個(gè)空接口CourseVisitor 使Course依賴(lài)這個(gè)接口從而達(dá)到隔離變化的目的。需要修改的是需要將courseVisitor Cast到具體的實(shí)現(xiàn)類(lèi),主要的代碼實(shí)現(xiàn)是:

       @Override
          void accept(CourseVisitor courseVisitor) {
              if (courseVisitor instanceof AOODCourseVisitor) {
                  ((AOODCourseVisitor) courseVisitor).visit(this);
              }
          }

       

      小B擼擼袖子,大筆一揮,修改代碼如下:

      public abstract class Course {
      
          protected GregorianCalendar startDate;
          protected int students;
          protected SimpleDateFormat dateFormat;
      
          public Course(GregorianCalendar startDate, int students) {
              this.startDate = (GregorianCalendar) startDate.clone();
              this.students = students;
              this.dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public GregorianCalendar getStartDate() {
              return startDate;
          }
      
          abstract void accept(CourseVisitor courseVisitor);
      }
      View Code
      public class AOODCourse extends Course {
      
          public AOODCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
          }
      
          @Override
          void accept(CourseVisitor courseVisitor) {
              if (courseVisitor instanceof AOODCourseVisitor) {
                  ((AOODCourseVisitor) courseVisitor).visit(this);
              }
          }
      }
      View Code
      public class JavaCourse extends Course {
      
          private GregorianCalendar endDate;
      
          public JavaCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
              endDate = (GregorianCalendar) startDate.clone();
              endDate.add(Calendar.DAY_OF_WEEK, 4);
          }
      
          @Override
          void accept(CourseVisitor courseVisitor) {
              if (courseVisitor instanceof JavaCourseVisitor) {
                  ((JavaCourseVisitor) courseVisitor).visit(this);
              }
          }
      
          public int getTotalComputers() {
              return students/2;
          }
      }
      View Code
      public class AndroidCourse extends Course {
      
          private GregorianCalendar endDate;
      
          public AndroidCourse(GregorianCalendar startDate, int students) {
              super(startDate, students);
              endDate = (GregorianCalendar) startDate.clone();
              endDate.add(Calendar.DAY_OF_WEEK, 4);
          }
      
          @Override
          void accept(CourseVisitor courseVisitor) {
              if (courseVisitor instanceof AndroidCourseVisitor) {
                  ((AndroidCourseVisitor) courseVisitor).visit(this);
              }
          }
      
          public int getTotalComputers() {
              return students/2;
          }
      }
      View Code
      public interface CourseVisitor {
      }
      View Code
      public interface AndroidCourseVisitor {
          void visit(AndroidCourse androidCourse);
      }
      View Code
      public interface AOODCourseVisitor {
          void visit(AOODCourse aoodCourse);
      }
      View Code
      public interface JavaCourseVisitor {
          void visit(JavaCourse javaCourse);
      }
      View Code
      public abstract class CourseReport {
      
          protected SimpleDateFormat dateFormat;
      
          public CourseReport() {
              dateFormat = new SimpleDateFormat("MM/dd/yyyy");
          }
      
          public String generateComputerReport(List courses) {
              StringBuffer report = new StringBuffer();
              CourseVisitor v = makeCourseVisitor(report);
              for (Iterator i = courses.iterator(); i.hasNext();) {
                  Course course = (Course) i.next();
                  report.append(dateFormat.format(course.getStartDate().getTime())).append(" ");
                  course.accept(v);
              }
              return report.toString();
          }
      
          protected abstract CourseVisitor makeCourseVisitor(StringBuffer report);
      }
      View Code
      public class CourseComputerReport extends CourseReport {
      
          public static void main(String[] param) {
              CourseComputerReport report = new CourseComputerReport();
              List<Course> courses = new ArrayList<>();
              courses.add(new AOODCourse(new GregorianCalendar(2015, 3, 20), 10));
              courses.add(new JavaCourse(new GregorianCalendar(2015, 3, 20), 10));
              courses.add(new AndroidCourse(new GregorianCalendar(2015, 3, 20), 10));
              System.out.println("Report is : " + report.generateComputerReport(courses));
          }
      
          @Override
          protected CourseVisitor makeCourseVisitor(StringBuffer report) {
              return new ReportCourseVisitor(report);
          }
      }
      View Code

       順便說(shuō)一下,上面使用的模式名稱(chēng)是Acyclic visitor, 是為了解決添加新的item 導(dǎo)致所有的item需要重新編譯和打包的問(wèn)題。

      posted on 2017-05-31 13:11  布兜兜  閱讀(489)  評(píng)論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 亚洲色一色噜一噜噜噜| 金门县| 亚洲人成人日韩中文字幕| 亚洲欧洲日韩国内精品| 天堂mv在线mv免费mv香蕉| 97色成人综合网站| 三级国产在线观看| 亚洲人成网站在线无码| 国产精品美女网站| 在线观看热码亚洲av每日更新| 亚洲人成网网址在线看| 亚洲精品中文av在线| 99久久精品国产熟女拳交| 激情久久av一区av二区av三区| 日韩精品人妻av一区二区三区| 欧美大屁股喷潮水xxxx| 亚洲最大的成人网站| 亚洲理论在线A中文字幕| 欧美成人午夜在线观看视频| 国产亚洲情侣一区二区无| 亚洲熟女综合色一区二区三区 | 99久久精品国产一区色| 亚洲线精品一区二区三八戒 | 欧美不卡无线在线一二三区观| 久久精品成人免费看| 内射人妻视频国内| 亚洲精品无码久久一线| 熟女一区二区中文字幕| 体态丰腴的微胖熟女的特征| 免费一区二区无码东京热| 乱人伦人妻中文字幕不卡| 91密桃精品国产91久久| 国产精品粉嫩嫩在线观看| 激情五月开心综合亚洲| 国产AV影片麻豆精品传媒| 亚洲欧美日韩综合久久久| 91精品国产午夜福利| 国产福利片一区二区三区| 剑河县| 天堂av色综合久久天堂| 色av综合av综合无码网站|