`
H_eaven
  • 浏览: 32219 次
  • 性别: Icon_minigender_1
  • 来自: 鲨堡
文章分类
社区版块
存档分类
最新评论

分离责任,消除代码级别耦合

阅读更多
例子--安全检查.
假设希望检查用户是否有权限执行某个方法,如果没有权限就抛出一个异常,也就是说对要执行安全检查的代码进行方法拦截,以加

入检查代码.如果编程解决这个问题,OO无法给我们任何有效的帮助.得到的是这样的代码.
public class MyBusinessObject implements BusinessObject {
   public void businessMethod1() throws UnauthorizedException {
      doSecurityCheck();
     // Do the work of method1
}
   public void businessMethod2() throws UnauthorizedException {
      doSecurityCheck();
     // Do the work of method2
}
   protected void doSecurityCheck() throws UnauthorizedException {
     
}
}


这个类有两个责任:主要责任是执行业务代码 Do the work of methodX.
                 次要责任是执行安全检查代码 doSecurityCheck.
OO可以尽可能减少重复的代码.如把安全检查代码归整到一个单独方法中去,但无法消除重复的代码,这要在每个业务方法中调用安

全检查方法.基于层级结构的OO对这种正交性的代码无法做到完全的消除重复代码.
Decorator模式:
//业务类
  public class MyBusinessObject implements BusinessObject {
   public void businessMethod1() throws UnauthorizedException {
     
     // Do the work of method1
}
   public void businessMethod2() throws UnauthorizedException {
     
     // Do the work of method2
}
 
}   
//装饰类
public abstract class BusinessObjectFilter implements BusinessObject {

   private BusinessObject target;
public BusinessObjectFilter (BusinessObject obj) {
   this.target = obj;
}
   public void businessMethod1() throws UnauthorizedException {
       this.target.businessMethod1();
}
   public void businessMethod2() throws UnauthorizedException {
     this.target.businessMethod2() ;
     
}

 
} 
//组合业务操作和安全检查的类
public class RealBusinessObject extends BusinessObjectFilter {
     public ReadBusinessObject(BusinessObject obj) {
           super(obj);
}
   //1.增加安全检查代码.
   //2.一定要调用super.businessMethod1();否则这将不是一个增强功能的方法,而是在重写一个方法.
   public void businessMethod1() throws UnauthorizedException {
       doSecurityCheck();
       super.businessMethod1();
}
   public void businessMethod2() throws UnauthorizedException {
doSecurityCheck();
     super.businessMethod2() ;
     
}
   protected void doSecurityCheck() throws UnauthorizedException {
     
}
}


通过Decorator模式的使用,可以将两者的责任分离,(如果安全检查代码过于复杂,可以用Extract Class将代码抽离出去).
但仍有两个问题:1.要针对每一个业务对象都要写一个装饰类。强类型在这里没有多大用处,如果一个通用类能解决问题则是最恰当

的.
               2.无论怎样分离代码,最后都要在一个地方将两者进行组装, 组装的动作发生在编译期。如果能在运行时组装则能

避免代码级别的耦合.利用AOP提供的方式则能做到这一点.

Observer模式.
将安全检查代码封装到接口中去,
//Observer
public interface SecurityCheck {
   void doSecurityCheck() throws UnauthorizedException;
}
//Observable
public class MyBusinessObject implements BusinessObject{
   private SecurityCheck securityCheck;
   public void businessMethod1() throws UnauthorizedException {
     securityCheck.doSecurityCheck();
     // Do the work of method1
}
   public void businessMethod2() throws UnauthorizedException {
     securityCheck.doSecurityCheck();
     // Do the work of method2
}
 public void setSecurityCheck(SecurityCheck securityCheck) {
   this.securityCheck = securityCheck;
}
}   



安全检查作为业务方法的一个次要逻辑.但Observable要通知Observer,则代码必然会发生耦合.

普通的代理模式的代码结构与上面Decorator模式基本相同.
OO设计在此问题上只能尽可能减少重复代码,尽量分离责任,但最后仍会发生代码的耦合.
AOP的总结最大成果在于提出了一套完备的切入点理论,以及让被增强的类完全对增强一无所知-- 从前的大多数拦截技术都没有做到

这一点.以实现责任在代码级别的解耦.
Dynamic Proxy
//业务类
  public class MyBusinessObject implements BusinessObject {
   public void businessMethod1() throws UnauthorizedException {
     
     // Do the work of method1
}
   public void businessMethod2() throws UnauthorizedException {
     
     // Do the work of method2
}
 
}   
//安全检查接口
public class SecurityCheckImpl implements SecurityCheck {
    public void doSecurityCheck() throws UnauthorizedException {
        //doSecurityCheck
    }
}

//组合业务类和安全检查的通用类
public class CommonSecurityCheck implements InvocationHandler {
   private Object target;
   private SecurityCheck securityCheck;
   private CommonSecurityCheck(Object arg0,SecurityCheck arg1) {
    this.target = arg0;
    this.securityCheck = arg1;
}
  public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
       this.securityCheck.doSecurityCheck();
       Object result = method.invoke(this.target,args);
       return result;
}
} 


某一业务类与安全检查代码在运行时进行组装.
分享到:
评论

相关推荐

    Metalama简介2.利用Aspect在编译时进行消除重复代码.doc

    通过使用Metalama,我们可以将关注业务逻辑的代码与关注横切关注点(如日志记录、事务管理、性能监控等)的代码分离,使得代码更加模块化,降低耦合,同时提升代码的可维护性和扩展性。这种编译时的AOP实现方式相比...

    代码规约及数据库设计规范.zip_alivesof_代码 规约 规范

    4. **代码结构**:代码应该有良好的层次结构,模块化设计,高内聚低耦合。每个类和方法都应有明确的职责,避免过大的类和过长的方法。 5. **代码风格**:保持统一的代码风格,如缩进、空格、换行等,使用IDE的代码...

    代码重构总结

    - **将查询操作同修改操作分开来**:将数据查询和数据修改操作分离,可以提高代码的清晰度和可维护性。 - **合并功能相似的子程序,并用参数来区分它们**:通过参数来区分相似子程序的不同行为。 - **通过传递不同的...

    orm工具策略和最佳实践源代码

    ORM工具的主要目标是消除数据访问层(DAO,Data Access Object)与业务逻辑层之间的耦合,通过对象模型抽象数据库操作,使代码更易于理解和测试。 描述中的“结合hibernate DAO示例”表明我们将深入研究如何利用...

    springAOP详解

    - **耦合度高**:业务逻辑和日志记录逻辑紧密耦合,不利于代码的扩展和重构。 **解决方案:** - **引入代理模式**:使用 Java 动态代理技术来创建一个代理对象,该对象能够在调用目标方法前后执行额外的操作(如...

    SpringCode.zip

    它通过默认配置来消除大量的XML配置,使开发者能够快速创建独立运行的、生产级别的基于Spring的应用。SpringBoot内置了Tomcat或Jetty服务器,可以快速启动一个Web应用,并且提供了许多开箱即用的功能,如自动配置、...

    重构糟糕设计的五步技能链

    2. **全局与成员变量读写函数分离**:通过分离读写操作,提高代码的安全性和可维护性。 3. **语句块间无交叠**:保持语句块之间的独立性,避免逻辑上的交叉。 4. **读程序要块读、不要行读**:鼓励按照逻辑块来阅读...

    毕业设计外文翻译(计算机专业)-Spring框架 (2).docx

    源代码级别的元数据功能让你可以将各种行为信息融入到代码中,类似于注解,增强了代码的灵活性和扩展性。 总的来说,Spring框架通过其七大模块——核心、上下文、DAO、ORM和AOP等,为开发者提供了全面且强大的工具...

    java框架总结ssm springboot等

    它消除了几乎所有的JDBC代码和手动设置参数及获取结果集的工作。MyBatis允许开发者将SQL语句直接写在XML配置文件中,或者使用注解的方式与Java对象映射,从而实现了SQL的灵活编写和数据库操作的简化。 MyBatis框架...

    基于SSH文献管理系统(代码+论文)

    它允许开发者以对象的方式处理数据库,消除了SQL语言与应用程序之间的耦合。Hibernate提供了透明的数据持久化服务,通过注解或XML配置文件可以轻松地将Java类映射到数据库表。 在"基于SSH文献管理系统"中,这三个...

    软件设计模式与重构大作业-心算大师游戏

    4. **消除重复代码**:提取共性功能为单独的方法或类,例如创建一个通用的事件监听处理方法。 5. **简化函数**:将过长的GameUI.count和Question.result函数拆分为更小、更专注的函数,减少函数的复杂性。 6. **...

    java框架核心技术笔记

    2. Hibernate:Hibernate是一个对象关系映射(Object-Relational Mapping,ORM)框架,它允许开发者用Java对象模型来处理数据库操作,消除了SQL与Java代码之间的耦合。Hibernate通过XML或注解来定义对象和数据库表...

    设计模式(16)-Bridge.pdf

    1. **解耦**:抽象化和实现化之间的紧密耦合被消除,两者可以独立变化,增加了系统的灵活性。 2. **开放封闭原则(OCP)**:通过组合,抽象化部分可以独立地增加新的行为,而无需修改现有代码。 3. **组合/聚合复用...

    毕业设计外文翻译(计算机专业)-Spring框架.pdf

    通过源代码级别的元数据功能,你可以将各种行为信息融入到你的代码中。 6. **Web模块**:Spring还包含Web相关的模块,如MVC(Model-View-Controller)框架,用于构建Web应用程序,提供了处理HTTP请求、视图渲染和...

    Mybatis的使用

    Mybatis 消除了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作,它允许开发者直接编写 SQL,同时保持良好的封装和解耦。以下是对 Mybatis 的详细讲解: 1. **Mybatis 概述** Mybatis 是由 Google Code ...

    S S H思想(文 档)

    2. 面向切面编程:Spring的AOP模块允许开发者定义“切面”,将关注点如日志、事务等分离出来,提高了代码的可维护性。 3. 数据访问:Spring JDBC和ORM(Object-Relational Mapping)支持,如Hibernate,简化了数据库...

    改善C#程序的50种方法2015

    40. **代码分层**:分离业务逻辑、数据访问和用户界面,提高代码可维护性和测试性。 41. **单元测试**:通过单元测试确保代码质量,尽早发现问题。 42. **代码审查**:定期进行代码审查,发现潜在的性能和设计问题...

    Spring+Mybatis+Springboot面试试题及答案.zip

    1. **依赖注入(DI)**: DI是Spring的核心特性,通过XML配置或注解方式实现对象间的依赖关系,使得代码更加松耦合,易于测试和维护。 2. **AOP**: AOP用于实现横切关注点,如日志记录、事务管理等,可以将这些通用...

    Java相关课程系列笔记之十四Hibernate学习笔记

    Hibernate作为ORM工具,旨在消除Java应用程序与SQL之间的耦合,通过将Java对象与数据库表进行映射,实现了对象的持久化。开发者无需编写大量的JDBC代码,从而提高开发效率和代码可维护性。 1.2 Hibernate访问数据库...

    Spring的web框架-外文翻译.pdf

    源码级别的元数据功能可以将各种行为信息融入代码中,类似注解。 6. **Web模块** Spring的Web模块专注于Web应用程序的开发,包括Spring MVC,这是一个强大且灵活的MVC框架,用于构建Web应用程序的控制器、视图和...

Global site tag (gtag.js) - Google Analytics