再学面向对象

📅 2026/7/8 8:48:23
再学面向对象
背景老师问当年学习java看的谁的视频第一节课讲的什么为什么学他的视频我啊啊啊经过同学一起回忆终于唤醒沉睡的记忆马士兵的课程讲了面向对象因为马士兵老师讲课实在风趣幽默会举各种通俗易懂的例子。我重新又看了视频形成今天的文章。导图如下一、开车去新疆如果用程序实现“开车去新疆”可以有几种设计方法至少可以想到两种面向过程面向对象。用面向过程实现车启动→踩油门→张家口→内蒙古→甘肃→新疆→熄火以我为主语如果想复用是复用具体的方法。用面向对象实现车.go()实现细节在车的go()方法里。我如果想去新疆直接执行go()方法具体要如何操作车要经过哪里只有车知道。看起来用面向对象实现“开车去新疆”我需要知道的信息更少具体细节都隐藏在了车里。如果有其他人也想去新疆看起来只用调用车.go()就行而不用知道发动机在哪油门在哪。。。那让人有个go()方法可以吗也可以。但面向对象中一般让合适的方法出现在合适的类。车启动、熄火等变化车最清楚所以封装到车中外部不需要知道。二、面向对象前面我们用开车去新疆的例子简单对比了面向过程和面向对象的差别那面向对象思想具体是怎样的我们该如何遵循面向对象的原则解决问题呢面向对象最基本的概念是类、对象其他概念都是基于类和对象展开的研究。1、类和对象的概念1、对象是用计算机语言对问题域中事物的描述对象通过属性(attribute)和方法(method)来分别对应事物所具有的静态属性和动态属性。2、类是用于描述同一类型的对象的抽象类中定义了这一类对象所因具有的静态和动态属性。3、类可以看成一类对象的模板对象可以看成该类的一个具体实例。举个例子用车举例类是对一类事物的抽象比如车是类丰田和大众是对象是对车类的实例化。我们指的某一辆车是指的对象比如嘿路上那辆大众跑的真快。而我们指的某一类车是指的类比如车按动力补给方式可以分为燃油车和新能源车。只有指具体某一个时才是指对象。从动态和静态的角度认识类还用上面的车的例子从动态和静态的角度认识类的属性和方法是这次再学习中印象深刻、感觉很有意思的点。为什么觉得有意思呢想想之前在类中都写了哪些方法gettersettertoString。业务中涉及到处理属性值的方法基本都是面向过程的写法用到哪写到哪一个方法洋洋洒洒几千行代码复用性极差。我认为从动态和静态的角度分析类的属性和方法是面向对象的起点。因为这样才是从宏观去分析业务分析当前的类把类里有什么都分析全了。类的内涵和外延更加明确能更好的被复用更好的和其他类建立关系。在Java中属性对应成员变量的概念。听马士兵老师讲完这段我觉得收获了一个很有意义的认识类的方法觉得很兴奋之前也看过但这次印象特别深刻真是经典永流传。2、类与类的关系在2.1中我们从动态和静态的角度认识了类的内部在2.2中我们通过UML中的6种关系认识类间的关系。认识了这6种关系对应到我们的业务中就知道该如何给类合理的建立关联。合理很重要理-是科学依据是前人总结的伟大经验不能仅仅是研发个人的经验更不能是一拍脑门UML 类间 6 大关系完整对照表耦合强度从强→弱排序关系名称中文别名核心语义记忆句式生命周期特点代码特征示例UML 图示泛化 Generalization继承子类是父类的特殊种类is-a是一种父子同生命周期子类复用父类class Sedan extends Car空心三角实线指向父类实现 Realization接口实现类遵守接口规范、履行契约遵循 XX 规范接口仅定义类独立实现class Car implements Drive空心三角虚线指向接口组合 Composition强组合、包含整体由部件构成部件不能脱离整体contains-a专属包含整体销毁部件同步销毁部件无法单独复用类内部构造器new部件对象实心菱形实线菱形在整体侧聚合 Aggregation弱聚合、拥有整体持有部件部件可拆分复用has-a拥有整体、部件生命周期相互独立部件可更换 / 转移通过 set / 构造传入外部已存在对象空心菱形实线菱形在整体侧关联 Association普通关联、引用两个类互相持有对方引用长期存在联系has-reference持有引用双方生命周期互不绑定平等关系作为成员变量定义无菱形普通实线可标多重度依赖 Dependency临时依赖、使用一个类方法内临时使用另一个类用完即无关use-a临时使用仅方法局部临时生效不存成员变量方法入参 / 局部变量 / 方法内 new 对象虚线箭头指向被依赖类举个栗子泛化小米 SU7extends汽车小米 SU7 是一种汽车实现汽车implements可行驶接口汽车实现行驶规范组合汽车包含发动机车报废发动机随之报废专属不可拆分聚合汽车拥有轮胎轮胎可拆下换到另一台车关联司机 ↔ 汽车司机长期持有车辆引用平等双向关联依赖年检工具类方法传入 Car 对象仅年检时临时使用车辆3、用面向对象分析问题2.1和2.2都是在讲方法马士兵老师把使用面向对象分析问题也总结出了三点也让我非常非常印象深刻1、找对象找出问题中涉及的所有对象技巧找名词2、分析类/对象用动态和静态视角确定属性和方法3、确定对象之间的关系这里就用到了2.2中的UML的6种关系。我们用这三步试一下”开车去新疆“1找对象找名词场景名词司机 (Driver)、汽车 (Car)、路线 (Route) → 三个类2区分静态属性、动态行为静态名词描述、特征品牌、颜色、姓名、途经城市等全部定义为私有成员变量配套 get/set动态动词动作启动车辆、开车、规划路线、展示城市定义为类的普通方法3确定类之间 UML 关系关联Driver 内部有Car myCar成员变量司机长期持有车辆双向稳定联系依赖planRoute(Route route)仅方法参数使用 Route只规划路线时临时依赖用完无绑定代码1. Route 路线类依赖被使用对象import java.util.List; /** * 路线类自驾新疆路线 */ public class Route { // 静态属性 private String routeName; // 路线名称 private ListString cityList; // 途经城市 // 构造 public Route(String routeName, ListString cityList) { this.routeName routeName; this.cityList cityList; } // getter setter public String getRouteName() { return routeName; } public void setRouteName(String routeName) { this.routeName routeName; } public ListString getCityList() { return cityList; } public void setCityList(ListString cityList) { this.cityList cityList; } // 动态方法打印路线途经城市 public void showCities() { System.out.println(路线【 routeName 】途经城市); for (String city : cityList) { System.out.print(city ); } System.out.println(); } }2. Car 汽车类关联对象/** * 汽车类 */ public class Car { // 静态属性 private String brand; // 品牌 private String model; // 型号 private String color; // 颜色 private String produceTime;// 出厂时间 private int seatNum; // 座位数 // 构造 public Car(String brand, String model, String color, String produceTime, int seatNum) { this.brand brand; this.model model; this.color color; this.produceTime produceTime; this.seatNum seatNum; } // getter setter public String getBrand() { return brand; } public void setBrand(String brand) { this.brand brand; } public String getModel() { return model; } public void setModel(String model) { this.model model; } public String getColor() { return color; } public void setColor(String color) { this.color color; } public String getProduceTime() { return produceTime; } public void setProduceTime(String produceTime) { this.produceTime produceTime; } public int getSeatNum() { return seatNum; } public void setSeatNum(int seatNum) { this.seatNum seatNum; } // 动态方法 public void start() { System.out.println(brand model 车辆启动); } public void drive() { System.out.println(正在沿高速行驶前往新疆); } public void addOil() { System.out.println(中途服务区加满油); } }3. Driver 司机类核心类体现关联 依赖/** * 司机类 * 关系说明 * 1. 关联持有Car成员变量长期拥有车辆 * 2. 依赖planRoute方法参数是Route方法内临时使用路线对象 */ public class Driver { // 静态属性 private String name; private int driveYear; // 关联关系成员变量持有Car private Car myCar; public Driver(String name, int driveYear, Car myCar) { this.name name; this.driveYear driveYear; this.myCar myCar; } // getter setter public String getName() { return name; } public void setName(String name) { this.name name; } public int getDriveYear() { return driveYear; } public void setDriveYear(int driveYear) { this.driveYear driveYear; } public Car getMyCar() { return myCar; } public void setMyCar(Car myCar) { this.myCar myCar; } // 动态方法开车自驾新疆 public void driveToXinJiang() { System.out.println(司机 name 驾龄 driveYear 年准备自驾新疆); myCar.start(); myCar.drive(); myCar.addOil(); } // 依赖关系方法入参传入Route临时使用路线对象 public void planRoute(Route route) { System.out.println(name 正在规划自驾路线); route.showCities(); } }4. 测试主类 Main完整运行演示import java.util.List; public class Main { public static void main(String[] args) { // 1. 创建汽车对象 Car su7 new Car(小米, SU7 Pro, 海湾蓝, 2026-03, 5); // 2. 创建司机对象关联绑定车辆 Driver driver new Driver(小张, 6, su7); // 3. 创建北京到新疆G7路线对象 ListString cityList List.of(北京, 张家口, 呼和浩特, 额济纳旗, 哈密, 乌鲁木齐); Route g7Route new Route(G7京新高速, cityList); // 4. 调用依赖方法传入路线对象 driver.planRoute(g7Route); System.out.println(); // 5. 自驾出发 driver.driveToXinJiang(); } }运行输出结果:小张正在规划自驾路线路线【G7京新高速】途经城市北京 张家口 呼和浩特 额济纳旗 哈密 乌鲁木齐司机小张驾龄6年准备自驾新疆小米SU7 Pro 车辆启动正在沿高速行驶前往新疆中途服务区加满油到这里我们又系统的认识了面向对象思想学习了动静结合去认识类用UML的6种关系建立类之间的关系并总结出了3个步骤处理实际的问题。之前模糊的点都找到了章法而不仅仅是个人经验了。三、为什么选择面向对象在第二节我们花了很大的功夫研究面向对象学习使用面向对象分析实际问题。为什么呢为什么选择使用面向对象呢首先因为面向对象思想能帮我们大大提升软件的复用性。软件会变化Lehman只适合长期演化系统→ 需要频繁修改 → 复杂性爆炸 →复用能减少重复修改的工作量。面向对象是复用整个对象包括对象的数据和方法相比之下面向过程的函数库只能复用行为方法数据结构和行为是分离的复用时需要自己重新组装——这就是面向对象复用颗粒度更粗、更整块的独有优势。其次使用面向对象思想帮我们更好解耦。高内聚、低耦合是面向对象的核心设计原则Parnas, 1972。每个类的内聚性高职责单一彼此之间通过 UML 的几种关系管理依赖尽可能松耦合 →修改时影响范围可控 → 降低修改成本。所以对于需要频繁修改的软件在设计时使用面向对象思想一方面通过数据行为绑定的独有优势提升复用性另一方面通过高内聚、低耦合的设计原则降低修改成本两方面共同减少开发和维护的工作量。面向对象思想的局限(个人经验)面向对象思想也有局限并不是能解决所有问题的银弹。1、OOP只适合会变化的软件不适合一次性脚本 / 性能极端敏感场景2、OOP增加了系统复杂度类多、间接调用多小项目反而过度设计3、OOP不适合无状态 / 纯计算场景函数式编程反而更自然。总结通过这次学习我深刻体会到了面向对象与面向过程在复用上的巨大差异更加明确了如何使用面向对象思想编程。面向对象复用性是对象级别复用整个对象的数据和结构复用粒度更大。面向过程的复用性是方法级别更适合变化频率低系统简单的场景。