1. 程式人生 > >#Java程式設計師福利:3分鐘知道Android開發所需要知道的知識基礎

#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層含義:

  1. 子類必須完全實現父類的方法
  2. 子類可以有自己的方法
  3. 當子類的方法過載父類的方法時,形參要比父類的範圍更大
  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;
   }
}