为了发挥java面相对象的巨大优势,实现:各司其职、可重用性、可扩展性、弱耦合性。体现封装继承多态三大特性。我们采用三层体系结构。
第一层:获得数据
第二层:处理数据
第三层:显示数据或者叫做数据交流
1、目的
当需求发生改变时,我们可以把改变局限在某个层次中,而不影响其他层次。例如,如果仓库的地点以及放置物品的位置发生改变的话,我们不需要对前台接待员和汽车修理工做过多的说明,只要让仓库保管员能够清楚应该怎么工作就可以了。同样的,如果某一个层次的需求发生变化,则我们只需要针对那个特定的层次,修改相应的代码,而不用改变其他层次的代码。
要实现弱耦合性,可以定义三个接口。
2、实现步骤
2.1定义三个接口
1、Dao层的接口,即获得数据的层次,只有一个方法即获得数据。
package dao;
public interface Dao {
String getData();
}
2.Biz层
有两个方法,一个处理数据的不用说,翻译、倒置、变大写小写等的实现。另一个方法说明是设置Dao属性,既然有一个属性那就设置它,所以说Dao是Biz里面的一个属性。一个对象的属性同时又是一个对象。
package biz;
import dao.Dao;
public interface Biz {
void setDao(Dao dao);
String dealData();
}
3、View层
同理的,因为View里面需要用到Biz的方法,然后把Biz作为View的一个属性,就可以调用他的方法了。既然是属性那就有一个设置属性的方法。
package view;
import biz.Biz;
public interface View {
void setBiz(Biz biz);
void showData();
}
2.2三个接口的实现类
1、Dao从文件中获得数据
注意看他们都是怎么建立文件的,都是各自建立的包,然后再 导入数据包,这样实现好分工。
package dao;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TextDao implements Dao {
@Override
public String getData() {
// TODO Auto-generated method stub
BufferedReader bu = null;
String str=null;
try {
FileReader fr=new FileReader("text.txt");
bu = new BufferedReader(fr);
str = bu.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
bu.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return str;
}
}
2、Biz处理数据
package biz;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import dao.Dao;
public class TranBiz implements Biz {
private Dao dao1;
@Override
public void setDao(Dao dao1) {
// TODO Auto-generated method stub
this.dao1=dao1;
}
@Override
public String dealData() {
// TODO Auto-generated method stub
String data=dao1.getData();
Map<String,String> dictionary=new HashMap<String,String>();
dictionary.put("hello", "你好");// V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。
dictionary.put("world", "世界");
dictionary.put("from", "来自");
dictionary.put("TextFile", "文本文件");
dictionary.put("TCPserver", "TCP服务器");
String[] ss=data.split(" ");//字符串拆分保存进一个数组中,这个一定要是空格,不然读不到数据
for(int i=0;i<ss.length;i++){
String v=dictionary.get(ss[i]);//V get(Object key); 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
ss[i]=v;
}
//利用StringBuilder再把字符串拼起来
StringBuilder sb=new StringBuilder("");
for(String s1:ss){
sb.append(s1);
}
data=sb.toString();
return data;
}
}
3、View
package view;
import biz.Biz;
public class ImplView implements View {
private Biz biz;
@Override
public void setBiz(Biz biz1) {
this.biz=biz1;
}
@Override
public void showData() {
// TODO Auto-generated method stub
String data=biz.dealData();
System.out.println(data);
}
}
4、主函数
注意看好,这里主函数中只是利用前面写好的三个类建立3个对象,然后代用他们里面的set方法,设置属性,建立了关联关系。
package helloworld;
import dao.*;
import biz.*;
import view.*;
public class TestHelloWorld {
public static void main(String[] args) {
// TODO Auto-generated method stub
Dao dao=new TextDao();
//Dao dao=new ImplDao();
//Biz biz=new ImplBiz();
Biz biz=new TranBiz();
View view=new ImplView();
//设置关联关系,biz里面有dao,view里面有biz
biz.setDao(dao);//这两步,不能没有,不然实现不了,设置好属性有了具体的值之后才能够在函数里边调用这个属性的方法。
view.setBiz(biz);
//打印显示数据
view.showData();
}
}
3、改进—配置文件+反射实现真正的开闭
不足之处:上面的代码,如果有哪一部分需要改变的话,就在那个部分新加一个实现类,然后在主方法中创建相对应的方法就可以了,但是,这样还不能真正的开闭。
3.1工厂模式+反射+配置文件创建对象
三个接口的代码及它的实现类的代码是不需要改变的,只需要创建一个工厂类,在工厂里面用配置文件+反射的方法写好创建那三个对象的方法。反射是通过读取配置文件,得到相应的字符串来创建对象,所以这种方式下需要创建哪个对象就直接修改配置文件就好。
工厂模式的代码 :用工厂创建对象,在主函数中调用工厂的方法即可。
package factory;
import dao.*;
import biz.*;
import view.*;
import java.io.*;
import java.util.*;
public class SimpleFactory {
private Properties pro;
public SimpleFactory(){
pro =new Properties();
InputStream is = null;
try {
is = new FileInputStream("config.txt");
pro.load(is);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public Dao createDao() throws Exception{
String className =pro.getProperty("dao");
Dao dao=(Dao) createObject(className);
return dao;
}
public Biz createBiz() {
String className =pro.getProperty("biz");
Biz biz = null;
try {
biz = (Biz) createObject(className);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return biz;
}
public View createView() {
String className =pro.getProperty("view");
View view = null;
try {
view = (View) createObject(className);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return view;
}
private Object createObject(String name) {
Object result=null;
try {
Class c=Class.forName(name);
result=c.newInstance();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
主函数的代码:
package helloworld;
import dao.*;
import biz.*;
import view.*;
import factory.*;
public class TestHelloWorld {
public static void main(String[] args) throws Exception {
SimpleFactory sim=new SimpleFactory();
Dao dao=sim.createDao();
Biz biz=sim.createBiz();
View view=sim.createView();
//设置关联关系,biz里面有dao,view里面有biz,先创建一个dao对象,然后把这个对象放进biz里面,这样才是真正的完成了设置。
biz.setDao(dao);
view.setBiz(biz);//同样的道理
//打印显示数据
view.showData();
}
}
4、三层体系结构之中异常的处理
如果出现了机场客户是看不到的,,那么我们怎让客户看到异常的情况呢?只能是在View层显示出异常信息,所以我们可以自定义异常,定义为未检查异常,然后一直抛出给View层,View层再捕获异常打印异常的原因。
4.1自定义异常
继承未检查异常,然后只需要写构造方法,第二个有信息的构造方法继承父类。
package exception;
public class HelloException extends RuntimeException{
public HelloException(){}
public HelloException(String msg){
super(msg);
}
}
4.2整体实现
1、Dao层
package dao;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TextDao implements Dao {
@Override
public String getData() {
BufferedReader bu = null;
String str=null;
try {
FileReader fr=new FileReader("text.txt");
bu = new BufferedReader(fr);
str = bu.readLine();
} catch (IOException e) {
//这里的变化,改变了之前的
//e.printStackTrace();
throw new exception.HelloException(e.getMessage());//先捕获异常,然后再抛出给Biz,Biz再往上传给View层然后在view层捕获打印信息。
}
finally{
try {
bu.close();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();这里的变化
}
}
return str;
}
}
2.view
package view;
import biz.Biz;
import exception.*;
public class ImplView implements View {
private Biz biz;
@Override
public void setBiz(Biz biz1) {
this.biz=biz1;
}
@Override
public void showData() {
try {
//在这里捕获异常
String data=biz.dealData();
System.out.println(data);
} catch (HelloException e) {
System.out.println("服务器维护中...");
}
}
}