关于FactoryBean的个人理解
有基本学生类结构:
1 package top.dreamcenter.test.bean; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Calendar; 5 6 public class Student { 7 private int age; 8 private Calendar birth; 9 10 public Student() {} 11 public Student(int age, Calendar birth) { 12 super(); 13 this.age = age; 14 this.birth = birth; 15 } 16 public int getAge() { 17 return age; 18 } 19 public void setAge(int age) { 20 this.age = age; 21 } 22 public Calendar getBirth() { 23 return birth; 24 } 25 public void setBirth(Calendar birth) { 26 this.birth = birth; 27 } 28 29 private String shortBirthString() { 30 if (birth == null) return "NULL"; 31 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 32 return sdf.format(birth.getTime()); 33 } 34 35 @Override 36 public String toString() { 37 return getClass().getSimpleName() 38 + ":{\n\tage:" + age + ",\n\tbirth:\"" + shortBirthString() + "\"\n}"; 39 } 40 }
基本方式创建类对象并初始化:
1 package top.dreamcenter.test.core; 2 3 import java.util.Calendar; 4 5 import top.dreamcenter.test.bean.Student; 6 7 public class Core { 8 public static void main(String[] args) { 9 Calendar now = Calendar.getInstance(); 10 int age = 0; 11 12 Calendar temp1 = Calendar.getInstance(); 13 temp1.set(2000, 12 - 1, 12); 14 age = now.get(Calendar.YEAR)-temp1.get(Calendar.YEAR); 15 Student zhangSan = new Student(age, temp1); 16 17 Calendar temp2 = Calendar.getInstance(); 18 temp2.set(2001, 3 - 1, 5); 19 age = now.get(Calendar.YEAR)-temp2.get(Calendar.YEAR); 20 Student liSi = new Student(age,temp2); 21 22 System.out.println(zhangSan); 23 System.out.println(liSi); 24 } 25 }
问题发现1:对象的初始化于主体中过于过于复杂
解决措施1:将对象的创建与初始化在对象自己内部暴露出来
public static Student getStudent(int year, int month, int date) { Calendar now = Calendar.getInstance(); Calendar temp = Calendar.getInstance(); temp.set(year, month - 1, date); int age = now.get(Calendar.YEAR)-temp.get(Calendar.YEAR); Student student = new Student(age, temp); return student; }
此时,main函数只要简短的两句即可创建:
Student zhangSan = Student.getStudent(2000, 12, 12);
Student liSi = Student.getStudent(2001, 3, 5);
问题发现2:如果在初始化时要求添加多个监听器,假如用解决措施1将会导致bean类实现了过多的接口
解决措施2:使用FactoryBean模式创建对象
// 基本学生类结构:1 package top.dreamcenter.test.bean; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Calendar; 5 6 public class Student implements Cloneable{ 7 private int age; 8 private Calendar birth; 9 private String name; 10 11 public Student() {} 12 public Student(String name, int age, Calendar birth) { 13 this.age = age; 14 this.birth = birth; 15 this.name = name; 16 } 17 18 protected String getName() { 19 return name; 20 } 21 22 public int getAge() { 23 return age; 24 } 25 public void setAge(int age) { 26 this.age = age; 27 } 28 public Calendar getBirth() { 29 return birth; 30 } 31 public void setBirth(Calendar birth) { 32 this.birth = birth; 33 } 34 35 public String shortBirthString() { 36 if (birth == null) return "NULL"; 37 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 38 return sdf.format(birth.getTime()); 39 } 40 41 @Override 42 protected Object clone() throws CloneNotSupportedException { 43 Student student = (Student)super.clone(); 44 student.birth = (Calendar)birth.clone(); 45 return student; 46 } 47 @Override 48 public String toString() { 49 return name + ":{\n\tage:" + age + ",\n\tbirth:\"" + shortBirthString() + "\"\n}"; 50 } 51 }
// 简易的信息改变监听器
package top.dreamcenter.test.core; public interface InfoListener { void onInfoChanged(); void closeListener(); }
// 工厂类创建
查看工厂类
---------------------------------------------------
禁止转载
1 package top.dreamcenter.test.bean; 2 3 import java.util.Calendar; 4 import java.util.HashSet; 5 import java.util.Iterator; 6 import java.util.Set; 7 8 import top.dreamcenter.test.core.InfoListener; 9 10 public class StudentFactoryBean implements InfoListener{ 11 private Student tempStudent; 12 private Set<MyThread> set; 13 private boolean isNotCheck; 14 15 public StudentFactoryBean() { 16 set = new HashSet<MyThread>(); 17 } 18 19 public Student getStudent(String name, int year, int month, int date) { 20 Calendar now = Calendar.getInstance(); 21 Calendar temp = Calendar.getInstance(); 22 temp.set(year, month - 1, date); 23 int age = now.get(Calendar.YEAR)-temp.get(Calendar.YEAR); 24 25 tempStudent = new Student(name, age, temp); 26 onInfoChanged(); 27 return tempStudent; 28 } 29 30 private class MyThread extends Thread{ 31 private Student myStudent; 32 private boolean check; 33 public MyThread() { 34 check = !isNotCheck; 35 myStudent = tempStudent; 36 } 37 public void run() { 38 try { 39 Student before = (Student) myStudent.clone(); 40 while(check) { 41 sleep(100); 42 if (myStudent.getAge()!=before.getAge() 43 ||!myStudent.shortBirthString().equals(before.shortBirthString())) { 44 System.err.println(myStudent.getName() + " info changed!"); 45 before = (Student) myStudent.clone(); 46 } 47 } 48 } catch (CloneNotSupportedException e) { 49 e.printStackTrace(); 50 } catch (InterruptedException e) { 51 e.printStackTrace(); 52 } 53 } 54 } 55 56 @Override 57 public void onInfoChanged() { 58 MyThread myThread = new MyThread(); 59 myThread.start(); 60 set.add(myThread); 61 } 62 63 @Override 64 public void closeListener() { 65 isNotCheck = false; 66 Iterator<MyThread> iterator = set.iterator(); 67 while(iterator.hasNext()) { 68 iterator.next().check = false; 69 } 70 } 71 }
// 测试示例
1 package top.dreamcenter.test.core; 2 3 import java.util.Calendar; 4 import java.util.Scanner; 5 6 import top.dreamcenter.test.bean.Student; 7 import top.dreamcenter.test.bean.StudentFactoryBean; 8 9 public class Core { 10 private static StudentFactoryBean sfb; 11 public static void main(String[] args) { 12 sfb = new StudentFactoryBean(); 13 14 Student zhangSan = sfb.getStudent("Zhang_San", 2000, 12, 12); 15 Student liSi = sfb.getStudent("Li_Si", 2001, 3, 5); 16 17 // 此时学生类都已经初始化好并且添加了信息变动监听器 18 19 System.out.println("set age :"); 20 while(true) { 21 Scanner scanner = new Scanner(System.in); 22 int age = scanner.nextInt(); 23 if (age == 0) break; 24 else if (age < 0) zhangSan.setAge(-age); 25 else liSi.setAge(age); 26 } 27 28 sfb.closeListener(); 29 System.out.println(zhangSan); 30 System.out.println(liSi); 31 } 32 }
所以FactoryBean出现的目的是让复杂的初始化问题简化,
并且让Bean本身更加的短小精悍,
同时降低了Bean本身对其它类或者接口的依赖性。
---------------------------------------------------
禁止转载
程序宅男