1.首先,先公布一下上次的程序的改进版本:
UserOp 类:
package com.superclass;
public interface UserOp {
public int execute(Request request,Response reponse);
}
Request 类:
package com.superclass;
import java.util.HashMap;
public class Request {
private HashMap requestData=new HashMap();
public void setProperties(String name,Object value){
requestData.put(name, value);
}
public Object getProperties(String name){
return requestData.get(name);
}
}
Response 类:
package com.superclass;
import java.util.HashMap;
public class Response {
private HashMap responseData=new HashMap();
public void setProperties(String name,Object value){
responseData.put(name, value);
}
public Object getProperties(String name){
return responseData.get(name);
}
}
QueryUser 类(查询的)
package com.op;
import com.data.User;
import com.superclass.Request;
import com.superclass.Response;
import com.superclass.UserOp;
public class QueryUser implements UserOp {
/* (非 Javadoc)
* @see com.superclass.UserOp#execute(com.superclass.Request, com.superclass.Response)
*/
public int execute(Request request, Response reponse) {
// TODO 自动生成方法存根
String userId=(String)request.getProperties("userId");
System.out.println("您所查询的用户Id为:"+userId);
User user=new User();
user.setUserId(userId);
user.setUserName("xxxx");
user.setPassWord("yyy");
reponse.setProperties("User", user);
return 0;
}
}
AddUser 类
package com.op;
import com.data.User;
import com.superclass.Request;
import com.superclass.Response;
import com.superclass.UserOp;
public class AddUser implements UserOp {
public int execute(Request request,Response reponse) {
int succ = 0;
User user=(User)request.getProperties("User");
System.out.println("添加用户的信息是:/n"+user+"/n添加成功");
succ = 1;
return succ;
}
}
UserFactory 类:
package com.factory;
import java.util.ResourceBundle;
import com.superclass.Request;
import com.superclass.Response;
import com.superclass.UserOp;
public class UserFactory {
public static UserOp getUserOp(String command) {
UserOp userOp=null;
ResourceBundle resource = ResourceBundle.getBundle("command");
String className=resource.getString(command);
try {
userOp=(UserOp)Class.forName(className).newInstance();
} catch (InstantiationException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
return userOp;
}
}
Controller 类:
package com.control;
import javax.swing.JOptionPane;
import com.data.User;
import com.factory.*;
import com.superclass.Request;
import com.superclass.Response;
public class Controller {
/**
* @param args
*/
public static void perform(Request request,Response response) {
// TODO 自动生成方法存根
String command=(String)request.getProperties("command");
UserFactory.getUserOp(command).execute(request, response);
}
}
调用方法:
package com.run;
import com.control.Controller;
import com.data.User;
import com.superclass.Request;
import com.superclass.Response;
public class DoAdd {
public static void main(String[] args) {
User user=new User();
user.setUserId("0000");
user.setUserName("mc");
user.setPassWord("mm");
Request request=new Request();
request.setProperties("userId", "1");
request.setProperties("command", "q");
Response response=new Response();
Controller.perform(request, response);
user=(User)response.getProperties("User");
System.out.println("您查询的用户信心是:"+user);
}
}
资源文件:command.properties
a = com.op.AddUser
d = com.op.DeleteUser
u = com.op.UpdateUser
l = com.op.UserLogin
q = com.op.QueryUser
通过上面的程序,我们真正实现了关于数据库的所有操作的封装,那么以后我们是添加什么功能,在上述代码的情况下,我们不用改动任何类,只需添加新类,和改配置文件就行了。
在这个例子中,应用了如下原则:
单一职责原则(高内聚)SRP(除了Controller类,它是作为控制类来用的)。
开闭原则 OCP 一个Controller类,一个UserFactory类,把原来的if语句改成配置文件了,并且使用Class.forName消除了与子类的关系,动态生成类.
里氏代换原则 LSP: 只要父类可以实现的用子类即可替换。反之不可。:主要是在Controller中,用父类实现的方法用子类能够替换(execute方法),但是在UserFactory中,用到的父类的地方用子类却不能替换。
依赖倒转原则 DIP(谑称“好莱坞原则”) 从Controller中可以看出,在原来中都是直接依赖关系,但本程序中这中依赖关系在编译时体现不出来,可以实现动态的改变类之间的关系。
接口隔离原则ISP: 这里没有多个接口,但是我们在接口里只写了一个方法,当然也可以写三个方法,但是这样的话会强迫客户接受不需要的方法。所以要么拆分接口,要么合并方法。
组合/聚合复用原则CARP:本例中没有直接体现。
迪米特法则LoD:在这里的Controller原来时与很多类建立了关系,但现在只和一个工厂类建立了关系,减少了与外界的接触。
由与在我的java培训笔记五里已经对该程序和OO设计原则有了详细的介绍,在这里就不多写了,有兴趣的同学可以查看我上一篇文章。
2.异常:
为什么要有异常:内部:设计时会产生缺陷,生产时也会产生缺陷,外部:用户使用时操作错误,还有不可控制的环境问题!以及一些不可预料的错误。
要控制问题:第一必须准确的定位问题所在,并能有效反馈;其次改进必须能持续,并能有效改正,只有这样才能形成良性循环。
异常则负责第一条任务。确定问题的所在。可以使用重构和测试来不断修正问题。
Basics of The UNIX Philosophy
Repair what you can — but when you must fail, fail noisily and as soon as possible.
UNIX哲学的基本原则
修复你能修好的—但是如果你必须失败,那就尽可能吵闹并快速的失败。
3.异常语法:
<1>.throw new Exception(); //main()方法不用再抛出异常了。
<2>.throws Exctption;
<3>.try{}catch(Execption e){};
4.异常的类继承结构:
|-OutOfMemory Error
|-InterNal Error
______ Error |-Unkonwn Error
Throwable | |-NullPointer Exception
______ Exception |-Runtime Exception |-.....
|-IO Exception
|-.......
异常的分类
Checked
需要使用try……catch语句包围或throws语句抛出的异常
及在编写代码是就确定异常处理策略,从而利用了编译时刻的检查机制,增强方法的契约。
Unchecked
不需要使用try……catch语句包围或throws语句抛出的异常
只有Runtime Exception不需要检查。
典型的运行时异常错误:如数组运行时越界!(不用Try,Catch包围。且一般运行时错误有可能是逻辑错误)
IllegalArgumentExcetpin("非法的参数异常");
5.自己编写异常类:
public class UserNameException extends RuntimeException{
public UserNameException(String msg){
super(msg);
}
}
一般用在系统设计时定义异常。
可以通过:throw new UserNameException("asdfasf");来实现。
6.多线程简介
<1>.线程本身自己不能申请时间片。是由系统随机分配的。
<2>.在对全局变量,数据库,文件访问时都会出现资源共享的问题。(可以折衷解决,将大资源分配成小资源dengdeng)
例如上面的Response 类,可以这么写 加上互斥锁:
package com.superclass;
import java.util.HashMap;
public class Response {
private HashMap responseData=new HashMap();
public synchronized void setProperties(String name,Object value){
responseData.put(name, value);
}
public synchronized Object getProperties(String name){
return responseData.get(name);
}
}
另外在涉及到多线程时多用局部变量。
5.类集框架:Collections Frameword
由三部分组成:
接口:包括Collection,List,Set,SortedSet,Map,SortedMap,Iterator
实现:集合框架中接口的具体实现类:HashSet,HashMap........
List有先后概念,Set没先后概念.List已经排好序了,Set没有排序。SortedSet是排好序的Set。
Map是映射,是有Key和Value关系的。
Iterator是遍历集合的迭代器。相当于游标。
Collection接口时一组允许重复的对象,Set接口继承Collection,但不允许重复,List 允许重复,且下标有先后顺序。
HashSet未排序,TreeSet排序。(都不允许重复).
ArratList 适用与随即访问,且不必在除尾部的任何位置插入或删去元素。
LinkedList 适用与要频繁的从列表的中间位置等进行插入和删除操作。
Map接口不是Collection接口的继承。而是从自己的用于维护键-值关联的接口层次结构入手。按定义,该接口描述了从不重复的键到值的映射。经常做为数据库映射的工作。Map的entrySet()方法返回一个实现Map.Entry接口的对象集合。集合中每个对象都是底层的Map中的一个特定的键-值对。通过这个集合迭代,您可以获得每一条目的键值或对应修改。在Map中插入、删除、定位元素,HashMap试最好的选择,如果排序(按"键"的顺序排列),可以用TreeMap。
HashMap map=new HashMap();
String keyset=map.keySet();
Iteratro it=keyset.iterator();
map.put("111","111");
while(it.hasNext()){
String key=it.next();
String value=map.get(key);
System.out.println(key+":"+value);
}
static变量会放在方法区,一般static程序块用来初始化类,或常量。
组合与聚合区别:
聚合的生命周期与引用类无关,组合与引用类有关。比如在一个类中引用单太类,那么单太类不随这个类的消失而消失。
组合是只生命周期与这个类有关,是在这个类中创建的,这个类消失了,那个就也消失了。
6.泛型
可以在类,变量,方法上加上<T>做为泛型,在类实例化时进行批量替换
比如:
package com.superclass;
import java.util.HashMap;
public class Request<E> {
private HashMap requestData=new HashMap();
public void setProperties(String name,Object value){
requestData.put(name, value);
}
public E getProperties(String name){
return (E) requestData.get(name);
}
public E getCommand(){
return (E) requestData.get("command");
}
}
其实泛型对基础数据类型比较好用,但是对处理逻辑时传递对象时不是特好用。
重点总结:基本数据类型,会有程序猜结果。字符串比较会考,会if-else switch case的转换。区分全局变量,类变量,成员变量,局部变量。数组字符串操作,判断输入的邮箱是否合法。类的装载的顺序。new 一个String 产生了几个对象,封装,单例,限定符范围。多态是重中之重,OO原则的概念。异常,还有用户的程序。让你设计一个结构实现开闭原则。或者让你写一个封装类,把数据很好的封装。
到这里java的培训就暂时结束了,在这里感谢培训老师张老师。谢谢他的讲座。让我受益颇多,因为这次讲座主要是以练习为主,所以课间基本没有,上面的那些代码都是访张老师写的,在这里声明一下。在下一周里将是数据库和web培训,到时我也会将笔记发上来的,大家一起学习,一起进步。