一、類設計的技巧
我們在設計類的時候絮重,就像在室內(nèi)設計一樣冤寿,怎么合理創(chuàng)建每個變量错妖,并安排每個方法,是非常重要的疚沐。一方面看起來更有專業(yè)的水平暂氯,便于自己和他人閱讀;另一方面亮蛔,也可以更清晰的在其他類或包中調(diào)用該類痴施,使得java的封裝性更好,健壯性更強究流,等等辣吃。
1、一定要將數(shù)據(jù)設計為私有
當然芬探,這里說一定神得,并不是說所有的數(shù)據(jù)都要這么做,在一些必要的數(shù)據(jù)上是可以放寬一些權(quán)限的偷仿;不過為了安全起見哩簿,設置成為私有,是為了其封裝性的良好酝静。其實最重要节榜,需要強調(diào)的就是:絕對不要破壞封裝性。當數(shù)據(jù)保持私有時别智,外部使用者就不用去直接調(diào)用這些數(shù)據(jù)宗苍,而是通過一個入口,一個方法訪問薄榛,這樣讳窟,使用者不需要知道內(nèi)部數(shù)據(jù)怎么組織的,只需要知道如何傳入數(shù)據(jù)敞恋,如何使用結(jié)果等就可以了丽啡。而且,這些數(shù)據(jù)也就避免了被訪問耳舅,從而防止被修改了碌上。
2倚评、對數(shù)據(jù)進行初始化
我們在創(chuàng)建對象之前浦徊,一定要對其初始化刻恭。對實例變量進行顯式的初始化是有一定必要的扎唾,因為如果讓系統(tǒng)對對象的一些變量進行初始化,那么我們有的時候不知道系統(tǒng)會提供怎樣的默認初始化值劲妙,這就會對數(shù)據(jù)的使用造成了一定的影響呢岗。比如說冕香,你在設計小轎車這類汽車的時候蛹尝,如果你不初始化它的輪胎數(shù)默認為int = 4;(或者更多)的話,而讓系統(tǒng)默認初始化值為0悉尾,這顯然是不符合實際的突那。
3、不是所有的變量或者域都需要獨立的訪問器和設定器(即getXxx和setXxx构眯,Xxx代表變量名)
當把數(shù)據(jù)或者說一些變量設置為private的時候愕难,需要對數(shù)據(jù)進行訪問和必要的修改的時候,是需要訪問器和更改器的惫霸,但是猫缭,并不是所有的都是如此。比如說對于一個雇員的工資而言壹店,是需要獲得或設置的猜丹,這是需要getSalary()和setSalary()方法的,但是對于雇員的姓名和雇傭日期等硅卢,一旦構(gòu)造了這個雇員對象射窒,就就應該禁止更改了。另外将塑,在對象中轮洋,常有一些不希望別人獲得或設置的實例對象,如一些地區(qū)的信息等抬旺。
4弊予、類中不要存在過多的方法,適當?shù)姆纸庖粋€類的功能
這里的”過多“到底是多少呢开财?這就要根據(jù)個人的經(jīng)驗而定了汉柒,但是,如果很復雜的一個類可以很明顯地分解成兩個或更多的簡單的類责鳍,這就需要將其分解碾褂。當然,也不能把一個很簡單的方法作為一個類历葛,這就顯然有些不合適了正塌,掌握好度就可以了。比如說:一個類可以包含這樣幾個方法:對數(shù)據(jù)獲取最大值恤溶,最小值乓诽,排序等操作,另一個類可以包含這樣幾個方法:對數(shù)據(jù)進行增加或刪除等操作咒程。
5鸠天、類名或者方法名要能夠體現(xiàn)各自的職責
這與變量一樣,一個類名或者方法名應該有自己一個能夠反映出其含義的名字帐姻。命名可以這樣寫:arraySort稠集,即對數(shù)組的排序奶段;如類名可以是Employee,即是雇員的類剥纷。這樣更清晰的給自己也給其他人方便的閱讀痹籍。
6、使用固定的格式對類進行定義:
在對類進行定義的時候晦鞋,可以按這樣的順序定義词裤,如:
//創(chuàng)建一個簡單的雇員類
import java.util.*;
public class Employee
{
public Employee(String name,int age,double salary)
{
//將變量定義為private
private this.name = name;
private this.age = age;
private this.salary = salary;
}
//訪問器方法
public String getName()
{
return name;
}
public int getAge()
{
if (age<18)//限制age的值
{
System.out.println("不好意思啦,我們不接收未成年人鳖宾!嘿嘿");
return;
}
return age;
}
public double getSalary()
{
return salary;
}
//修改雇員工資:漲byPercent個百分點的工資
public void setSalary(double salary,double byPercent)
{
salary + = salary*byPercent/100;
}
}
你可以先將特定包中的類導入吼砂,在創(chuàng)建構(gòu)造器,然后創(chuàng)建變量和方法等等鼎文,當然這種風格不是固定的渔肩,重要的是,你在定義自己的所有類的時候都要遵循自己的風格拇惋,讓類設計出來更統(tǒng)一周偎,這樣更顯專業(yè)。
一撑帖、繼承設計的技巧
下面是一些對設計繼承關(guān)系的建議
1蓉坎、將公有成員放在超類中
這里的成員包括成員變量和成員方法。這樣既可以減少代碼的重復編寫胡嘿,避免出錯(代碼越多蛉艾,越容易出錯);還可以增強封裝性衷敌,是程序更健壯勿侯。
2、盡量不要使用受保護的變量(即被protected修飾)
很多人認為缴罗,將大多數(shù)的實例變量定義為protected是很不錯的助琐,這樣的話,子類就能在需要的時候直接訪問它們了面氓。但是兵钮,使用protected修飾并不能得到更好的保護作用,究其原因在于:
第一舌界、子類如果不被聲明為final的話掘譬,其他程序員是可以向下派生出子類的,這樣就可以直接訪問該類中protected的成員禀横,那么屁药,所謂的封裝性就會被破壞了粥血。
第二柏锄、protected修飾的成員是可以被同一包中的所有類訪問的酿箭,無論是不是這個類的子類,這樣趾娃,依然是對數(shù)據(jù)產(chǎn)生一定的危險缭嫡。
3、使用繼承實現(xiàn)子父類關(guān)系
使用繼承可以節(jié)省很多的代碼抬闷,但是要防止被隨意使用妇蛀。比如說,鐘點工同樣有姓名和年齡笤成,但是他們和公司雇員是不一樣的评架,是沒有所謂的工資的,因為他們是按小時獲得勞動報酬的炕泳。不會有雇員一樣的薪資待遇的纵诞。所以,如果在Employee類(假設有一個Manager子類)再派生出一個子類Contrator培遵,顯然是不合理的浙芙,因為在Employee中的類似打印工資單的方法,是不適用于鐘點工的籽腕。所以說嗡呼,要清楚是否兩個類之間有子父類的關(guān)系,在使用繼承皇耗。
4南窗、使用繼承的方法有有意義,否則不要使用繼承關(guān)系
對于可以相互轉(zhuǎn)換的兩類事物郎楼,使用繼承是不好的矾瘾。比如說,假日也是一天箭启,可以將假日作為一周或者一個月的子類考慮壕翩,但是假日是可以轉(zhuǎn)換為非假日的,那么這就不太合適了傅寡。
5放妈、在覆蓋方法時,不要改變預期的行為
在覆蓋一個方法的時候荐操,不應該隨意改變行為的內(nèi)涵芜抒,應該是由于超類的方法不適宜子類的應用,或者有缺陷的時候托启,才覆蓋該方法宅倒。如果我們自己不慎重考慮覆蓋的方法是否有意義,編譯器是不會知道該方法是否有任何意義屯耸,只要語法沒有錯誤拐迁,是可以通過編譯的蹭劈。
6、使用多態(tài)线召,而非類型信息
對于下面的代碼:
if(x is of type1)
action1(x);
else if(x is of type2)
action2(x);
這就需要考慮使用多態(tài)了铺韧。
如果action1和action2表示的是相同的內(nèi)容,就可以定義一個方法缓淹,將其放置在兩個類的超類或者接口中哈打,然后就直接調(diào)用x.action(),因為JVM虛擬機可以動態(tài)綁定x是屬于那種類型讯壶,這樣可以節(jié)省很多代碼料仗,提高執(zhí)行效率,而且更有利于對代碼進行維護和擴展伏蚊。
下面是舉例:
class Employee
{
//將變量定義為private
private String name;
private double salary;
public Employee(String name,double salary)
{
this.name = name;
this.salary = salary;
}
public String getName()
{
return name;
}
public double getSalary()
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
}
class Manager extends Employee
{
private double bonus = 0;
public Manager(String name,double salary)
{
//調(diào)用超類Employee中的構(gòu)造器
super(name,salary);
}
//獲得Manager類中對象的salary罢维,有額外的獎金
public double getSalary()
{
double baseSalary = super.getSalary();
return baseSalary + bonus;
}
public void setBonus(double bonus)
{
this.bonus = bonus;
}
}
class ManagerText
{
public static void main(String [] args)
{
Manager boss = new Manager("Anna",80000);
boss.setBonus(5000);
Employee[] staff = new Employee[3];
staff[0] = boss;//由于boss是Manager類的,是Employee的子類丙挽,所以肺孵,是可以賦值給staff數(shù)組中的元素的
staff[1] = new Employee("Ben",50000);
staff[2] = new Employee("Jone",40000);
for(int i=0;i<staff.length;i++)
{
System.out.println("name = " + staff[i].getName() + ",salary = " + staff[i].getSalary());
}
}
}
7、不要過多的使用反射
反射機制使得人們可以通過在運行是查看變量和方法颜阐,讓人們能編寫出更具有通用性的程序平窘。這種功能對于便攜系統(tǒng)程序來說極其實用,但是通常不適用于編寫應用程序凳怨。反射是很脆弱的瑰艘,即編譯器很難幫助人們發(fā)現(xiàn)程序中的錯誤。任何錯誤只能在運行時才被發(fā)現(xiàn)肤舞,并導致異常紫新。