美文网首页
Java先收着以后再研究

Java先收着以后再研究

作者: 9842d350648c | 来源:发表于2019-04-03 14:43 被阅读0次

今年的Google IO 大会上,Google宣布Kotlin成为Android的官方语言,有兴趣的可以去学习下,Java作为android的第一个语言,还是需要把打这部分知识打牢固的。(这部分内容只是当作自己的复习)

1、三大特性

Java做为面向对象的语言,他的三大特性:继承、封装、多态。

2、6大原则

单一职责原则(Single Responsibility Principle)

定义: 不要存在多于一个导致类变更的原因。也就是说,一个类只负责一项职责

案例:工厂A负责生产面包和牛奶,当生产面包的需求发生变化时,需要改变工厂生产模式,这事就有可能影响牛奶的生产。

解决方案:遵循单一职责原则,分别建立两个子公司,一个负责生产面包,一个负责生产牛奶,这样如果面包需求变了就不会影响牛奶的生产了。

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 list = new ArrayList();

for(int i=0;i<20;i++) {

list.add(new Student());

}

classMonitor.count(list)

}

}

class ClassMonitor {

public void count(List 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 list;

public ClassMonitor(List list) {

this.list = list;

}

public void count(List list) {

System.out.println("班长说:全班的人数是。。。"+list.size());

}

}

class Student {

}

public class Test {

public static void main(String [] args) {

List list = new ArrayList();

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 list = new ArrayList();

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()+" 价格:"+ 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 list = new ArrayList();

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()+" 价格:"+ 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;

}

}

收藏一下慢慢研究!

相关文章

  • Java先收着以后再研究

    今年的Google IO 大会上,Google宣布Kotlin成为Android的官方语言,有兴趣的可以去学习下,...

  • MARK:微信web开发者工具

    先标记一下,以后再研究....

  • 蓖澜椠|第9章·白鸽囚玉簪

    “可.......太子也不在席间啊……” “不如........公主先收着?” “待何时见了,再还......” ...

  • 好方先收着

    1、牛皮癣 麻黄6克桂枝10克防风10克鸡屎藤30克桃仁6克红花6克生地20克白芍12克当归12克紫草9克白茅根9...

  • 前后端统一AES加密解密

    前后端统一AES加密解密,不考虑vi,先直接用,以后再深入研究。 前端代码 后端代码

  • iOS 之 第三方库

    将来有可能用到,先收着吧!

  • 勤奋,不足以让你过上好日子

    今天的文不短, 会给大家再理清一个概念 ——勤奋 建议:逐字阅读,没时间先收着 全文约为4000字 | 建议阅读时...

  • SSM框架搭建(maven+IDEA+Mac)

    【前言】首先,先吐槽一下Java,本人有一点点Java基础,仅限语法,这个月开始接触Java,先研究了一下Java...

  • 先计划好,以后再轻松

    今天要开始写论文了,时间还挺紧张的。幸好,我看到去年写的几篇论文的框架,正好拿来给里边填充内容,省了很多时间,瞬间...

  • 先关注使用,再研究原理

    刚开始很不习惯,对于还没搞清楚的方法先拿来直接用?有效吗?为什么它有效?是不是有什么隐藏的前提条件?....内心充...

网友评论

      本文标题:Java先收着以后再研究

      本文链接:https://www.haomeiwen.com/subject/rzqzbqtx.html