Java面向对象

说说你读面向对象的理解?

在Java面万事万物皆为对象。面向对象就是把一个对象抽象成具体的类,我们需要它来实现什么功能,它有什么特性,需要做什么事情,然后把这些特性和功能抽象成类的属性和方法。一个类代可能是一个具体事务的抽象,也可能对某一类功能的封装。
站在类的层面来说,可以利用封装、继承、多态等特性来功能的制定规范、扩展、类的复用等等。类与类之间可以恰当的用设计模式和遵循一些设计原则来进行类之间的继承、组合,达到可复用性、可扩展性、可维护性等目的。


六大设计原则
  • 里氏置换原则
    只要父类出现的地方子类就能够出现,而且替换为子类不会产生任何错误或异常。这个原则在策略模式中就有很好的体现,父类通常是一个接口,统一算法簇的行为,子类做具体实现,场景类在引用的时候传入的参数是接口,而不是其实现类,用的是算法簇父类的引用,指向子类的实现,这里也体现了多态。总结起来就是父类的引用指向子类的对象。

  • 依赖倒置原则
    首先它是一种类的依赖关系(局部变量、方法参数、静态方法的调用)
    而依赖倒置原则的本质其实就是通过抽象(抽象类或接口)使各个类或模块的实现彼此独立,不相互影响,实现模块间的松耦合,其实就是面向接口编程,各个模块之间的子类都是依赖各个模块的父类接口,而不是实现类,这样子达到松耦合。
    1、 高层模块不依赖底层模块,两者都应该依赖抽象(抽象类或接口)
    2、抽象不依赖具体实现类
    3、具体实现类依赖抽象
    这就是面向接口编程(OOD)的精髓之一
    列子:

public class Luffy {
    //luffy吃苹果
    public void eat(Apple apple) {
        apple.eat();
    }
}
public class Apple {
    //只有吃苹果
    public void eat() {
        System.out.println("吃苹果");
    }
}
//测试类
public class Test {

    public static void main(String[] args) {
        Luffy luffy = new Luffy();
        Apple apple = new Apple();
        luffy.eat(apple);
    }
}

这样子设计的话Luffy只会吃苹果,因为eat()的类型限定死了,显然这是不科学的,Luffy还需要吃梨子、香蕉等等。可以看到这里的Luffy和Apple两个实现类形成了依赖关系,这显然违背了我们设计原则,可扩性差,也不符合实际情况。改进:
让Luffy实现 IPerson接口,让Apple实现IFood接口:

public interface IPerson {
    void eat(IFood food);
}

public interface IFood {
    void eat();
}

public class Luffy implements IPerson{
    @Override
    public void eat(IFood food) {
        // TODO Auto-generated method stub
        food.eat();
    }
}

public class Apple implements IFood{
    //只有吃苹果
    public void eat() {
        System.out.println("吃苹果");
    }
}
public class Test {

    public static void main(String[] args) {
        Luffy luffy = new Luffy();
        Apple apple = new Apple();
//      Banner banner = new Banner();
        luffy.eat(apple);
//      luffy.eat(banner);
    }
}

这样子让抽象IPerson依赖IFood,具体实现交给Luffy和Apple、Banner。通过抽象不会造成Luffy类和Apple等类的依赖关系,松耦合,还可以扩展Jason吃梨子等等功能。

2.png

可以看到在改进之前类之间有依赖关系,改进后通过接口进行了松耦合。依赖的只是高层抽象接口。

  • 接口隔离原则
    接口隔离原则比较简单,就是定义的一个接口按照需求和其责任细分,不要把太多的抽象定义在一个接口。
    1、接口尽量小,不能出现臃肿的接口,在进行拆分接口的同时,一定要满足单一职责原则
    2、接口要高内聚,尽量少的对外公布public方法
    3、一个接口只负责一个子模块的逻辑
    但是在实际开发过程中要根据开发经验和实际情况设计接口的粒度,不能完全按照接口隔离原则,粒度越小,接口类越多,越难维护。粒度越大,灵活性降低。

  • 单一职责原则
    定义:应该仅有一个原因引起类的变更,也就是一个类只有一个职责。
    在我们在设计接口的时候,可能一个接口定义了好几种行为,这样的话一个接口就承担了多种职责,职责不明确,比如:

public interface ILuffy {
    String getName();   
    void eat();
}

一个接口定义了获取人名(属性)的职责,还定义了吃这个行为,所以一接口承担了两种职责。可以进行如下改进:

public interface IAttrs {
    void setAge(int age);
}
public interface IAction {
    void eat();
}

上面的例子在于年龄、名字等等属于属性,吃东西属于行为,需要不同的接口来承担不同的责任。
解决办法:将不同的职责分为不同的接口即可。
那么单一职责原则的意义何在呢?
降低类的复杂性,实现什么样的职责都有清晰的定义
提高可读性
提高可维护性
降低变更引起的风险,对系统扩展性和维护性很有帮助
但是、使用单一职责原则有一个问题,“职责”没有一个明确的划分标准,如果把职责划分的太细的话会导致接口和实现类的数量剧增,反而提高了复杂度,降低了代码的可维护性。所以使用这个职责的时候还要具体情况具体分析。建议就是接口一定要采用单一职责原则,实现类的设计上尽可能做到单一职责原则,最好是一个原因引起一个类的变化。
单一职责不仅仅用在类中,也同样适用方法。

  • 迪米特法则
    也称最少知识原则。一个类应该对他耦合或调用的类知道的最少。
    迪米特法则有一个原则就是“只和朋友类交流”,什么是朋友类呢?每个对象都有与其相耦合的类,两个对象之间的耦合被称为朋友关系,这种关系有很多比如:聚合、组合、依赖。
    有这么个故事:体育老师让体育委员确认班上的女生到齐了没有,对他说:“你去清下班上女生”,体育委员:“亲....亲那个(羞羞)?”
3.png
public class Teacher {
    
    public void commond(GroupLeader groupLeader) {
        ArrayList<Gril> arrayList = new ArrayList<>();
        arrayList.add(new Gril());
        arrayList.add(new Gril());
        arrayList.add(new Gril());
        groupLeader.countGrils(arrayList);
    }
}

public class GroupLeader {

    public void countGrils(List<Gril> grils) {
        System.out.println("女生的人数:" + grils.size());
    }
}

public class Gril {
}

public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.commond();
    }
  • 定义了一个Teacher类和一个commond发送指令的方法,方法里面实例了一个GroupLeader对象,然后定义了一个Grils数组,让GroupLeader去清点人数。最后的结果:女生的人数:3。
    虽然说目的是达到了,但是这里的设计是有问题的。Teacher对象只有一个朋友类——GroupLeader,有人会认为Gril不是吗?不是在方法里面有调用,然后形成了依赖关系。但是按照定义:只有一个对象是另一个对象的成员变量或者作为方法参数传入的才能称为是朋友类。在这里Gril并不是,但是有出现在commond方法体里面和Gril类有了交流。迪米特法则告诉我们只与朋友里交流,这里违背了这一原则。
    这样就破坏了Teacher类的健壮性。方法是一个类的行为,在方法里面竟然不知道与另外一个类的依赖关系,这个严重违反了迪米特法则。
    经过改进后的类图:
4.png
public class Teacher {
    public void commond(GroupLeader leader) {
        leader.countGrils();
    }
}
public class GroupLeader {
    private List<Girl> grils;

    public GroupLeader(List<Girl> grils) {
        this.grils = grils;
    }

    public void countGirls() {
        System.out.println("女生的人数:" + grils.size());
    }
}
public static void main(String[] args) {
        Teacher teacher = new Teacher();
        ArrayList<Gril> arrayList = new ArrayList<>();
        arrayList.add(new Gril());
        arrayList.add(new Gril());
        arrayList.add(new Gril());
        GroupLeader groupLeader = new GroupLeader(arrayList);
        teacher.commond(groupLeader);
    }

这样把Gril类的初始化放在了场景类中,在GroupLeader中增加了对Girl类的注入,避开了Teacher对Girl的访问,降低了耦合。
迪米特法则的核心就是实现类之间的解耦,弱耦合,只有弱耦合之后,类的复用率才可以提高。其结果就是会产生大量的中间类,增加了系统的复杂性,和维护难度

  • 开闭原则
    开闭原则算是前5中原则的一个抽象总结,没有一个固定的模式,但是最终保证的是提高程序的复用性、可维护性等要求。
    对扩展开放,对修改关闭。意思是我们需要扩展一个功能的时候是通过扩展接口来实现,而不是通过修改源码。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容