java面向对象设计原则之合成复用原则示例详解
作者:guoyp2126 发布时间:2023-11-09 16:55:51
概念
尽量使用合成/聚合,而不是使用继承实现复用。所谓的合成/聚合是指一个对象里持有另外一个类的对象,通过调用这些对象的方法得到复用已有功能的目的。如:报文解译程序中,按照继承复用可以设计为:
子类调用父类的方法即可完成水文报文解译、气象解译中通用方法;子类中一定包含了父类的方法,这个叫继承复用。
按照合成/聚合原则设计为:
水文协议和气象协议中,持有编码和位制转换对象,通过调用对象方法即可完成复用。
示例
数据库连接的复用:首先看通过集成关系复用数据连接代码如下
public class SqlServerConnect {
private Connection con = null;
public Connection getCon() {
System.out.println("创建数据库连接");
return con;
}
}
public class UserDao extends SqlServerConnect {
//继承复用连接数据
public void queryData()
{
Connection con =getCon();
String sql = "select * from emp";
try {
Statement statement = con.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
UserDao继承了SqlServerConnect,复用了父类的getCon()方法;如果此时数据库不再使用SQLServer,要改成oracle,这种复用就无能为力了。
使用合成复用,代码可以修改为:
//增加一个接口
public interface DatabaseConnection {
Connection getCon();
}
//SqlServerConnect实现该接口
public class SqlServerConnect implements DatabaseConnection {
private Connection con = null;
@Override
public Connection getCon() {
System.out.println("创建数据库连接");
return con;
}
}
//clsUserDaoNew和数据库连接接口呈现聚合关系,使用依赖倒置,可动态替换此类,复用了getCon()代码
public class UserDaoNew {
private DatabaseConnection objCon;
public UserDaoNew(DatabaseConnection conn){
objCon = conn;
}
public void queryData() {
Connection con = objCon.getCon();
String sql = "select * from emp";
try {
Statement statement = con.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
在UserDaoNew类中,通过使用聚合关系,通过构造注入一个数据连接对象,通过调用这个对象的getCon()方法实现复用。这种方式,利用里氏代换和依赖倒置原则,当使用SQLServer数据库时,注入SqlServerConnect实例,如果使用oracle数据库时,注入OrcaleConnect实例,代码更加灵活,实现动态复用。
拓展
1.继承是静态复用,通过聚合复用是动态复用。所谓的静态复用是在编码阶段已经明确了类之间的关系;动态复用则是在程序运行阶段,根据实际要求注入相应的对象完成复用的,动态复用比静态复用更具有灵活性。
2.合成复用原则还体现复用范围扩大了。如上图所示,使用继承关系,则BCD转ASCII码只服务报文解译,如一个加密程序也要使用BCD转ASCII、数据位制转换,就没办法使用。
来源:https://blog.csdn.net/guoyp2126/article/details/113946537


猜你喜欢
- 1、静态代码块①、格式在java类中(方法中不能存在静态代码块)使用static关键字和{}声明的代码块:public class Code
- 上下文:程序运行需要的环境(外部变量)上下文切换:将之前的程序需要的外部变量复制保存,然后切换到新的程序运行环境系统调用:(用户态陷入操作系
- spring-AOP 及 AOP获取request各项参数AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事
- 一、前言在SpringBoot工程(注意不是SpringCloud)下使OpenFeign的大坑。为什么不用SpringCloud中的Fei
- 本文实例讲述了Android开发实现标题随scrollview滑动变色的方法。分享给大家供大家参考,具体如下:要实现某个view的背景透明度
- 程序是这样的:static void Main(string[] args){ SmtpClient c
- Flutter有个悠久的传统,便是运行flutter create并删除所有内容,然后在所有标准样板文件(boilerplate)当中尽力复
- 权限上篇文章 Android 获取IP和UA中提及了获取WIFI的IP地址,本篇文章介绍下如何扫描WIFI。官方文档根据官方文档描述,扫描W
- 对Element和Node有困惑是因为对xml整个结构不了解,以下作为一个简要概述:以下图为w3c.org网站的xml文档树图:从上图可以看
- 意图:想将项目用到的两个dll库文件(CryptEnDe.dll和ICSharpCode.SharpZipLib.dll)一同编译进exe中
- 现在有一张订单表t_stockorder,其拥有id、code、client_id、merchandise_id、merchandise_n
- 本文实例讲述了Android自定义ViewPager的方法。分享给大家供大家参考,具体如下:package com.rong.activit
- package com.ysh.file;import java.util.ArrayList;import java.util.Linke
- FPS是什么?FPS (每秒传输帧数(Frames Per Second))【摘自百度百科】FPS是图像领域中的定义,是指画面每秒传输帧数,
- 背景近期在调研一个开源仓库,于是将 代码 从github下载后,当IDEA sync依赖时出现Cannot resolve org.four
- Android onClick 与 setOnClickListener区别为Android Widgets添加点击事件处理函数又
- 本文实例讲述了Java Bean与xml互相转换的方法。分享给大家供大家参考,具体如下:XML和Java Bean互相转换是一个很有用的功能
- IntInt是Java八种基本数据类型之一,一般大小为4字节32位,取值范围为2-31—231。两个Int类型变量用“==”比较的是值的大小
- 本文实例为大家分享了android多媒体音乐播放器的具体实现代码,供大家参考,具体内容如下首先,在AndroidManifest.xml中配
- 首先给大家来讲一个我们遇到的一个奇怪的问题:1.我的一个springboot项目,用mvn install打包成jar,换一台有jdk的机器