#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;
   }
}

猜你喜欢

转载自blog.csdn.net/qq_43202482/article/details/84317325