#Java程式設計師福利:3分鐘知道Android開發所需要知道的知識基礎
今年的Google IO 大會上,Google宣佈Kotlin成為Android的官方語言,有興趣的可以去學習下,Java作為android的第一個語言,還是需要把打這部分知識打牢固的。(這部分內容只是當作自己的複習)
1、三大特性
Java做為面向物件的語言,他的三大特性:繼承
、封裝
、多型
。
2、6大原則
單一職責原則(Single Responsibility Principle)
定義: 不要存在多於一個導致類變更的原因。也就是說,一個類只負責一項職責
案例:工廠A負責生產麵包和牛奶,當生產麵包的需求發生變化時,需要改變工廠生產模式,這事就有可能影響牛奶的生產。
解決方案:遵循單一職責原則,分別建立兩個子公司,一個負責生產麵包,一個負責生產牛奶,這樣如果麵包需求變了就不會影響牛奶的生產了。
如果有想學習java的程式設計師,可來我們的java學習扣qun:79979,2590免費送java的視訊教程噢!小編是一名5年java開發經驗的全棧工程師,整理了一份適合18年學習的java乾貨,送給每一位想學的小夥伴,歡迎大家一起學習哦。
public class Factory { public Factory () { super(); } public void product() { System.out.println(“生產餅乾”); System.out.println(“生產葡萄乾”); } }
public class Main {
public static void main (String [] args) {
new Factory.product();
}
}
遵循單一職責原則,做如下修改:
public class FactoryA { public void product() { System.out.println(“生產餅乾”); } } public class FactoryB { public void product() { System.out.println(“生產葡萄乾”); } }
public class Factory {
private FactoryA mA;
private FactoryB mB;
public Factory () {
super();
mA = new FactoryA();
mB = new FactoryB();
}
public void product() {
mA.product();
mB.product();
}
}
我理解的單一職責原則就是在開發過程中儘量將一些類的職責明確、唯一。
遵循單一職責的優點:
- 降低複雜度
- 提高可讀性
- 降低對其他功能的影響
可是可能由於職責的顆粒化,我們往往會違背這個原則,這個原因為職責擴散(就是因為某些原因,我們要吧職責之一再次細分)
關於這部分請看 單一職責原則(1)
里氏替換原則 (Liskov Substitutiion Principle)
定義:所有引用基類的地方必須能夠透明地使用其子類的物件
通俗的說,就是用父類的地方可以用子類去代替,但是用子類的地方用父類不一定能代替。
里氏替換原則包含4層含義:
- 子類必須完全實現父類的方法
- 子類可以有自己的方法
- 當子類的方法過載父類的方法時,形參要比父類的範圍更大
- 當子類的方法實現父類的抽象方法時,方法的返回值要比父類更嚴格
例子:
public class Test {
public static void main(String [] args) {
Man m = new Man();
}
}
abstract class Cat {
public void eat(){}
}
/**
* 人可以喂貓吃東西,可以有不同種類的貓
*/
class Man {
private Cat mCat;
public void setCat(Cat mCat) {
this.mCat = mCat;
}
public void feed() {
mCat.eat();
System.out.println("正在進食...");
}
}
class Garfield extends Cat {
@Override
public void eat() {
System.out.println("加菲貓進食...");
}
}
class Folds extends Cat {
@Override
public void eat() {
System.out.println("折耳貓進食...");
}
}
優點: 可以對後期版本升級,增添子類時都可以很好的維護
依賴倒置原則(Dependence Inversion Principle)
定義: 高層模組不應該依賴底層模組,應該依賴其抽象,抽象不應該依賴其細節,細節應該依賴其抽象。
底層模組:負責基本的操作
高層模組:由多個底層模組組成,負責複雜的操作
抽象:在Java中指的是介面或者抽象類
依賴倒置的核心思想是面向介面程式設計,相對於細節的多變性,抽象的穩定性更高一些。以抽象為基礎搭建起來的架構比以細節搭建起來的框架穩定的多。下面我們用例子來解釋下依賴倒置原則。
class Bread {
public String getContent () {
return "麵包生產出來了"
}
}
class Factory {
public void poduct(Bread bread) {
System.out.println("工廠開始生產");
System.out.println(book.getContent());
}
}
public class Test {
public static void main(String [] args) {
Factory mFactory = new Factory();
mFactory.poduct(new Bread());
}
}
假如現在需求變了,不再生產麵包,改為生產牛奶,這個時候工廠是做不了的,它只能生產麵包。這樣的話耦合性就會很高了。
遵循以來倒置的原則,我們做如下修改:
interface Model {
public String getContent();
}
class NewBread implements Model {
public String getContent() {
return "麵包生產出來了"
}
}
class Milk implements Model {
public String getContent() {
return "牛奶生產出來了"
}
}
class Factory {
public void product(Model model) {
System.out.println("工廠開始生產")
System.out.println(model.getContent());
}
}
public class Test {
public static void main(String [] args) {
Factory mFactory = new Factory();
mFactory.product(new NewBread());
mFactory.product(new Milk())
}
}
依賴有三種寫法
1、建構函式傳遞依賴
class Factory {
private Model model
public Factory(Model model) {
this.model = model;
}
public void product () {
System.out.println("工廠開始生產")
System.out.println(model.getContent());
}
}
2、setter方法傳遞
class Factory {
private Model model
public void setModel(Model model) {
this.model = model;
}
public void product () {
System.out.println("工廠開始生產")
System.out.println(model.getContent());
}
}
3、介面傳遞依賴
如 最開始給的例子
介面隔離原則 (Interface segregation Principle)
定義:客戶端不應該依賴它不需要的介面,類間的依賴關係應該建立在最小的介面上。
我們用一個例子來說明下:
interface I {
public void m1();
public void m2();
public void m3();
public void m4();
}
class B implements I {
public void m1() {
System.out.println("類B實現介面I的方法1");
}
public void m2() {
System.out.println("類B實現介面I的方法2");
}
public void m3(){}
public void m4(){}
}
class A {
public void depend1(I i) {
i.m1();
}
public void depend2(I i) {
i.m2();
}
}
class C {
public void depend1(I i) {
i.m3();
}
public void depend2(I i) {
i.m4();
}
}
class D implements I {
public void m1() {
}
public void m2() {
}
public void m3(){
System.out.println("類D實現介面I的方法3");
}
public void m4(){
System.out.println("類D實現介面I的方法4");
}
}
public class Client {
public static void main(String [] args) {
A a = new A();
a.depend1(new B());
a.depend2(new B());
C c = new C();
c.depend1(new D());
c.depend2(new D());
}
}
可以看到,對了類B來說 方法3和方法4是不需要的,但是由於介面I中有這兩個方法,所以必須實現它。同理,對於類D來說,方法1和方法2是不需要的。這樣的話就不符合介面隔離原則,下面我們修改一下以符合其原則:
interface I {
public void m1();
public void m2();
}
interface I1 {
public void m3();
public void m4();
}
class B implements I {
public void m1() {
System.out.println("類B實現介面I的方法1");
}
public void m2() {
System.out.println("類B實現介面I的方法2");
}
}
class A {
public void depend1(I i) {
i.m1();
}
public void depend2(I i) {
i.m2();
}
}
class C {
public void depend1(I1 i) {
i.m3();
}
public void depend2(I1 i) {
i.m4();
}
}
class D implements I1 {
public void m3(){
System.out.println("類D實現介面I的方法3");
}
public void m4(){
System.out.println("類D實現介面I的方法4");
}
}
我理解的介面隔離原則是:建立單一的介面,儘量介面細化,不要建立臃腫的介面,介面中的方法儘量少。
介面隔離原則是對介面進行的規範約束,應該要主要一下幾點(摘自《設計模式之禪》)
- 介面儘量小
介面在遵循單一職責原則的情況下,儘量減少和介面中方法,不不是無休止的細化介面。
- 高內聚
高內聚是提高介面、類、模組的處理能力,減少對外的互動。在介面中儘量少公佈public方法,介面是對外的承諾,承諾越少對外越有利,變更的風險也就越少,同時有利於降低成本
- 定製服務
根據需求分析,必要時為特殊使用者提供定製的介面,儘量避免不同操作人群使用同一介面,這樣會降低系統的享用速度和擴充套件性。
- 介面設計是有限度的
根據開發情景劃分設計介面,在開發過程中介面設計的顆粒度越小,系統靈活性越高。並不是以為的將介面細化。
迪米特法則(Low of Demeter,LoD)
定義
:一個物件應該對其他物件有最少的瞭解,只與直接的朋友通訊。
朋友關係
:每個物件都必然會與其他物件有耦合關係,兩個物件之間的耦合關係就稱為朋友關係。
迪米特法則定義的是類之間的關係要低耦合,一個類中的朋友不要太多,這樣後期維護起來比較方便。
舉個例子:老師清點人數,老師通過班長清點人數。
public class Teacher {
public void command (ClassMonitor classMonitor) {
List<Student> list = new ArrayList<Student>();
for(int i=0;i<20;i++) {
list.add(new Student());
}
classMonitor.count(list)
}
}
class ClassMonitor {
public void count(List<Student> list) {
System.out.println("班長說:全班的人數是。。。"+list.size());
}
}
class Student {
}
public class Test {
public static void main(String [] args) {
new Teacher().command(new ClassMonitor());
}
}
在Teacher類中,一個方法呼叫的兩個類的例項,分別是ClassMonitor和Student類。對於Teacher類來說,朋友類只有ClassMonitor,迪米特法則告訴我們只與朋友類通訊,所以這種設計就違反了迪米特法則。
在Java中朋友的定義為:出現在成員變數。方法的輸入輸出類稱為朋友類,在方法體內的類不屬於朋友類
我們改進一下,以複合迪米特法則
public class Teacher {
public void command (ClassMonitor classMonitor) {
classMonitor.count();
}
}
class ClassMonitor {
List<Student> list;
public ClassMonitor(List<Student> list) {
this.list = list;
}
public void count(List<Student> list) {
System.out.println("班長說:全班的人數是。。。"+list.size());
}
}
class Student {
}
public class Test {
public static void main(String [] args) {
List<Student> list = new ArrayList<Student>();
for(int i=0;i<20;i++) {
list.add(new Student());
}
new Teacher().command(new ClassMonitor(list));
}
}
迪米特法則給類的低耦合提出了四個基本要求
1. 只和朋友類交流
2. 朋友間也是有距離的
在java中的實現思想就是:類A與類B之間有依賴關係,並在方法輸入或輸出中建立該類的例項,那麼他們屬於朋友類,但是類A不可以過分操作類B的方法
3. 是自己的就是自己的
如果一個方法放在本類中,既不增加類間關係,也對本類不產生負面影響,那就放置在本類中
4. 謹慎使用serializable
開閉原則(Open Closed Principle,OCP)
定義:一個軟體實體如類、模組和函式應該對擴充套件開發,對修改關閉。即軟體實體應儘量在不修改原有程式碼的情況下進行擴充套件。
軟體實體包括:
- 專案或軟體產品中按照一定的邏輯規則劃分的模組
- 抽象和類
- 方法
一個例項
- IMilk 定義了兩個屬性:廠商和價格
- Supermarket是超市
- NovelMilk是一個具體的實現類
public class Supermarket {
public static List<NovelMilk> list = new ArrayList<NovelMilk>();
static {
list.add(new NovelMilk("伊利", 60))
list.add(new NovelMilk("安慕希",55))
}
public static void main(String [] args) {
for(NovelMilk milk: list) {
System.out.println("牛奶廠商" + milk.getManufacturers()+"\t 價格:"+ milk.getPrice()+ "元")
}
}
}
interface IMilk {
public String getManufacturers();
public int getPrice();
}
class NovelMilk implements IMilk {
private int price;
private String manufacturers;
public NovelMilk(String manufacturers, int price) {
this.manufacturers = manufacturers;
this.price = price;
}
@Override
public int getPrice() {
// TODO Auto-generated method stub
return this.price;
}
@Override
public String getManufacturers() {
// TODO Auto-generated method stub
return this.manufacturers;
}
}
需求更改:超市進行打折促銷,規定 50元以下的 9折出售。
如果要在NovelMilk中修改的話,修改量就會很大,而且違背了開閉原則,
解決方案:通過擴充套件實現變化
public class Supermarket {
public static List<NovelMilk> list = new ArrayList<NovelMilk>();
static {
list.add(new OffNovelMilk("伊利", 60))
list.add(new OffNovelMilk("安慕希",55))
}
public static void main(String [] args) {
for(NovelMilk milk: list) {
System.out.println("牛奶廠商" + milk.getManufacturers()+"\t 價格:"+ milk.getPrice()+ "元")
}
}
}
interface IMilk {
public String getManufacturers();
public int getPrice();
}
class NovelMilk implements IMilk {
private int price;
private String manufacturers;
public NovelMilk(String manufacturers, int price) {
this.manufacturers = manufacturers;
this.price = price;
}
@Override
public int getPrice() {
// TODO Auto-generated method stub
return this.price;
}
@Override
public String getManufacturers() {
// TODO Auto-generated method stub
return this.manufacturers;
}
}
class OffNovelMilk extends NovelMilk{
public OffNovelMilk(String manufacturers, int price) {
super(manufacturers, price);
// TODO Auto-generated constructor stub
}
@Override
public int getPrice() {
int rePrice = super.getPrice();
int nowPrice = 0;
if(rePrice<50){
nowPrice = rePrice*90/100;
}else{
nowPrice = rePrice;
}
return nowPrice;
}
}