20180206 反射中模块化开发的上课思路
一、写Dao文件
package cn.sgy.reflection1.exer; public interface Dao { public void insert(User user) ; public void delete(User user); }
二、写MySQLDao文件,实现Dao 接口后重写Dao的方法
package cn.sgy.reflection1.exer; public class MySQLDao implements Dao{ @Override public void insert(User user) { System.out.println("向MySQL插入用户对象:"+ user.getName()); } @Override public void delete(User user) { System.out.println("从MySQL中删除用户对象:"+ user.getName()); } }
三、写OracleDao文件,实现Dao 接口后重写Dao的方法
package cn.sgy.reflection1.exer; public class OracleDao implements Dao{ @Override public void insert(User user) { System.out.println("向Oracle中插入用户:"+ user.getName()); } @Override public void delete(User user) { System.out.println("从Oracle中删除用户:"+ user.getName()); } }
四、写User用户类
package cn.sgy.reflection1.exer; import java.sql.Date; public class User { private String name; private int age; private char gender; private Date birth; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } }
五、【重点】Service层,也分别写insert 和delete 方法
1、最开始 每次换数据库都要修改代码 重启程序
package cn.sgy.reflection1.exer; public class Service { public void insert() { User user = new User(); MySQLDao dao = new MySQLDao(); dao.insert(user); } public void delete() { User user = new User(); MySQLDao dao = new MySQLDao(); dao.delete(user); } public static void main(String[] args) { Service s= new Service(); s.insert(); } }
2、把dao的定义提到两个方法的外面 依然很麻烦
package cn.sgy.reflection1.exer; public class Service { private Dao dao = new MySQLDao();public void insert() { User user = new User(); dao.insert(user); } public void delete() { User user = new User(); dao.delete(user); } public static void main(String[] args) { Service s= new Service(); s.insert(); } }
3、引入properties思想(右击项目工程->new -> File)
如何调用properties,先想到的是构造函数,但是弊端在与有多少个Service就要在每个Service类里写多少个properties方法
private Properties prop = new Properties();
核心代码
1、 prop.load(new FileInputStream("config.properties"));
2、 String name = prop.getProperty("Dao");
从Properties中读取字符串
3、 Class<Dao> clz = (Class<String>) Class.forName(name);
根据字符串产生Dao的字节码(用的是第三种方法) 字符串—>字节码
4、 return clz.newInstance();
根据字节码产生对应的Dao实例对象
package cn.sgy.reflection1.exer; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class Service { private Dao dao ; private Properties prop = new Properties(); { try { prop.load(new FileInputStream("config.properties")); String name = prop.getProperty("Dao"); Class<Dao> clz = (Class<Dao>) Class.forName(name); dao = clz.newInstance(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void insert() { User user = new User(); dao.insert(user); } public void delete() { User user = new User(); dao.delete(user); } public static void main(String[] args) { Service s= new Service(); s.insert(); } }
六、如果有第二个Service那四行核心代码就又需要再写一遍 ,于是为了减少冗余 引入Factory(产生Dao的工厂)共用同一个Properties 所以一个工厂就够了,可以吧这个工厂设置为单例的
Service里面换成这个句子
private Dao dao =DaoFactory.getFactory().getDaoInsance();
这里使用的是单例的饿汉式方式
// 饿汉式---在创建实例的时候就把这个实例初始化的方式 private static TaskManager tm = new TaskManager();//先提供一个本类对像 private TaskManager() { //本类构造函数私有化 } public static TaskManager getInstance() { //提供一个本类的获取TaskManager的方法 return tm; }
public static void m() { } }
DaoFactory.java
package cn.sgy.reflection1.exer; import java.io.FileInputStream; import java.util.Properties; //工厂模式 public class DaoFactory { private static DaoFactory factory = new DaoFactory(); private Properties p = new Properties(); private DaoFactory() { } public static DaoFactory getFactory() { return factory ; } @SuppressWarnings("unchecked") public Dao getDaoInsance() { try { p.load(new FileInputStream("config.properties")); String name = p.getProperty("Dao"); Class<Dao> clz = (Class<Dao>) Class.forName(name); return clz.newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } }
config.properties Dao=cn.tedu.reflection.exer.MySQLDao Service=cn.tedu.reflection.exer.VIPService
七、拓展 自定义 delete等方法
八、深化: 一个Service 里面一个Dao 对象 , Service不止一个 ,Service 可以和Dao解耦 ,前台获取数据之后Service来处理,不止一个Service 时候前台如何处理这么多数据?
Model.class收取数据 不能直接放入数据库 要经过UserService的校验
package cn.tedu.reflection.exer; import java.util.Scanner; public class Model { // private Service service = ServiceFactory.getFactory().getServiceInstance(); private Service service = CommonFactory.getFactory().getInstance(Service.class); public void insertUser() { User user = new User(); // Scanner s = new Scanner(System.in); // user.setName(s.nextLine()); // user.setAge(Integer.parseInt(s.nextLine())); // user.setGender(s.nextLine().charAt(0)); // s.close(); user.setName("Amy"); user.setAge(25); user.setGender('男'); // 需要把User存储到数据库 service.insert(user); } public void delUser() { User user = new User(); Scanner s = new Scanner(System.in); user.setName(s.nextLine()); s.close(); UserService service = new UserService(); service.delete(user); } public static void main(String[] args) { Model m = new Model(); m.insertUser(); } }
把数据获取和数据处理分开
package cn.tedu.reflection.exer; public class UserService implements Service { // private Dao dao = DaoFactory.getFactory().getDaoInstance(); private Dao dao = CommonFactory.getFactory().getInstance(Dao.class); public void insert(User user) { System.out.println("普通客户处理中~~~"); if(user == null){ throw new NullPointerException("用户不能为空!!!"); } if (user.getAge() < 0) { throw new IllegalArgumentException(user.getName() + "不合法!"); } if (user.getGender() != '男' && user.getGender() != '女') { throw new IllegalArgumentException(user.getGender() + "不合法!"); } if (user.getName() == null || user.getName().length() <= 0 || user.getName().length() > 5) { throw new IllegalArgumentException(user.getName() + "不合法!"); } // 向数据库中插入数据 dao.insert(user); } public void delete(User user) { dao.delete(user); } }
提供Service类
package cn.tedu.reflection.exer; public interface Service { public void insert(User user); public void delete(User user); }
用UserService和VIPService实现Service
这时Model出现耦合 所以通过ServiceFactory来解决
核心代码
private Service service = ServiceFactory.getFactory().getServiceInstance();
p.load(new FileInputStream("config.properties"));
String name = p.getProperty("Service");
Class<Service> clz = (Class<Service>) Class.forName(name);
return clz.newInstance();
config.properties文件
Dao=cn.tedu.reflection.exer.MySQLDao Service=cn.tedu.reflection.exer.VIPService
再产生一个更通用的Factory,通过泛型选择哪个Factory
package cn.tedu.reflection.exer; import java.io.FileInputStream; import java.util.Properties; public class CommonFactory { private static CommonFactory factory = new CommonFactory(); private Properties prop = new Properties(); private CommonFactory() { } public static CommonFactory getFactory() { return factory; } @SuppressWarnings("unchecked") public <T> T getInstance(Class<T> inf) { try { prop.load(new FileInputStream("config.properties")); String name = inf.getSimpleName(); Class<T> clz = (Class<T>) Class.forName(prop.getProperty(name));//获取到了键 return clz.newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } }