`
zhyuan
  • 浏览: 2863 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论
阅读更多
  最近在看设计模式方面的资料.突发灵感,从数据库的连接中联想到了5种设计模式.然后编写了下,都能实现,可能有些实现方式在实际生产环境中并没有意义.就当是对设计模式的学习吧.
     首先上演的就是策略模式.我们在连接数据库时,并非一种数据库,比如,有时是MySql,有时是Oracle,有时又换到SQL Server,都要涉及数据库的切换.此时.我们就可以将数据库连接的算法封装起来,使它们可以相互替换.
     首先我们定义一个策略接口,用来表示数据库的连接.
Java代码 
package strategy; 
 
public interface Strategy { 
 
    public void getConnDB(); 
 


     然后我们实现了对具体的策略类:三大数据库的连接.我们在这里只是强调模式的实现,简单起见,不实现JDBC的连接的具体操作.下面的也是一样.
Mysql:
Java代码 
public class MysqlStrategy implements Strategy { 
    public void getConnDB() { 
        /*try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            String url = "jdbc:mysql://localhost/myDB?user=root&password=123456&useUnicode=true&characterEncoding=utf-8";
            Connection connection = DriverManager.getConnection(url);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }*/ 
        System.out.println("connect MySQL"); 
    } 


Oracle:
Java代码 
public class OracleStrategy implements Strategy { 
     
    public void getConnDB(){ 
         
        System.out.println("connect  oracle"); 
         
    } 
 


SQL Server:
Java代码 
public class SQLStrategy  implements Strategy{ 
    public void getConnDB(){ 
            System.out.println("connect  SQL SERVER"); 
        } 
    } 

策略应用场景,方便在运行时动态选择具体要执行的行为.
Java代码 
public class ClientContext { 
    Strategy strategy; 
     
    public ClientContext(Strategy strategy){ 
         
        this.strategy=strategy; 
    } 
     
    public void getConnDB(){ 
        strategy.getConnDB(); 
    } 
 


下面就开始测试了:
Java代码 
public class StrategyTest { 
    public static void main(String[] args) { 
        /**
         * 策略模式实现对Oracle的连接操作.
         */ 
        ClientContext occ = new ClientContext(new OracleStrategy()); 
        occ.getConnDB(); 
        /**
         * 策略模式实现对Mysql的连接操作.
         */ 
        ClientContext mcc = new ClientContext(new MysqlStrategy()); 
        mcc.getConnDB(); 
        /**
         * 策略模式实现对SQL Server的连接操作.
         */ 
        ClientContext scc = new ClientContext(new SQLStrategy()); 
        scc.getConnDB(); 
 
    } 
 


    这样,就基本完成通过策略模式动态切换数据库连接的算法.如果想实现对DB2,Sybase,PostgreSQL数据库的操作.只需实现策略接口即可.这样就可以任意扩展.同时对客户(StrategyTest 类)隐藏具体策略(算法)的实现细节,彼此完全独立。完全做到高内聚,低耦合.

     到这里,突然改变需求,需要在数据库连接之前增加一些日志的打印输出.按照传统的做法,我们修改每一个具体的实现类,增加这些功能,如果先前我们实现的具体类非常多.这无异是一笔不小的负担.而且也违反了开闭原则(OCP).
    这里大家可能想到在学习Spring AOP常提到的用AOP打印日志的情景.AOP主要用到了代理模式.这里我们也通过代理模式来实现.由于抽象策略类是接口,所以我们采用JAVA 反射中提供的代理.
   代理模式具体实现:
Java代码 
public class ProxyDB implements InvocationHandler { 
 
    private Object target; 
 
    public ProxyDB(Object target) { 
        this.target = target; 
    } 
 
    /**
     * 此处为我们要额外添加的方法 进行日志的打印输出
     */ 
    public void printLog() { 
        System.out.println("---------------打印输出点日志----------"); 
    } 
 
    /**
     * 代理业务处理器
     */ 
    public Object invoke(Object proxy, Method method, Object[] args) 
            throws Exception { 
        printLog(); 
        return method.invoke(this.target, args); 
    } 
 
    public static void main(String[] args) { 
        /**
         * 
         * 通过代理模式在连接Mysql前增加日志的打印输出;
         * 
         */ 
        MysqlStrategy ms = new MysqlStrategy(); 
        ProxyDB proxyCorps = new ProxyDB(ms); 
        Strategy realObject = (Strategy) Proxy.newProxyInstance(ms.getClass() 
                .getClassLoader(), ms.getClass().getInterfaces(), proxyCorps); 
        realObject.getConnDB(); 
 
        /**
         * 通过代理模式在连接 Oracle前增加日志的打印输出;
         * 
         */ 
        OracleStrategy os = new OracleStrategy(); 
        ProxyDB proxyCorps1 = new ProxyDB(os); 
        Strategy realObject1 = (Strategy) Proxy.newProxyInstance(os.getClass() 
                .getClassLoader(), os.getClass().getInterfaces(), proxyCorps1); 
        realObject1.getConnDB(); 
 
        /**
         * 通过代理模式在连接 SQL Server前增加日志的打印输出;
         * 
         */ 
        SQLStrategy ss = new SQLStrategy(); 
        ProxyDB proxyCorps2 = new ProxyDB(ss); 
        Strategy realObject2 = (Strategy) Proxy.newProxyInstance(ss.getClass() 
                .getClassLoader(), ss.getClass().getInterfaces(), proxyCorps2); 
        realObject2.getConnDB(); 
 
    } 
 


    

    难道只能通过代理来增加日志功能?这时又突然想到装饰者(Decorator),它本来的目的就是对类的实例追加或扩展附加功能.它可以动态的改变一个对象方法的行为.同时也满足设计原则中的开闭原则.
     装饰者模式
(Decorator):
Java代码 
public class Decorator implements Strategy { 
 
    private Strategy strategy; 
 
    public Decorator(Strategy strategy) { 
        this.strategy = strategy; 
    } 
 
    /**
     * 额外增加的功能,
     * 通过装饰者模式动态改变原来对象方法的行为.
     */ 
    public void printLog() { 
        System.out.println("---------------先打印输出点日志----------"); 
    } 
 
    public void getConnDB() { 
        printLog(); 
        strategy.getConnDB(); 
    } 
 
    public static void main(String[] args) { 
         
        /**
         * 在Oracle连接前增加日志的输出
         */ 
        Decorator decorator = new Decorator(new OracleStrategy()); 
        decorator.getConnDB(); 
        /**
         * 在Mysql连接前增加日志的输出
         */ 
        Decorator decorator1 = new Decorator(new MysqlStrategy()); 
        decorator1.getConnDB(); 
        /**
         * 在Mysql连接前增加日志的输出
         */ 
        Decorator decorator2 = new Decorator(new SQLStrategy()); 
        decorator2.getConnDB(); 
    } 


       呵呵, 这里大家可以比较一下代理模式和装饰者模式的区别.

    有时候,为了安全起见,我们并不像暴露每个具体的数据库连接类给客户.减少客户与后台具体类的依赖关系.提高子系统的独立性和可移植性. 这是需要我们提供一个简单接口,统一跟外界打交道.这时,就该我们的门面模式(Facade)上场了.

Facade外观模式:
    为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口,使子系统更加容易使用。在构建一个层次化的系统的时候,可以使用Facade模式定义系统的每一层的入口,如果层与层之间是相互依赖的,则可以限定他们仅通过Facade进行通信,从而简化了层与层之间的依赖关系。
    同时也实现了软件设计原则中的迪米特法则(LCP).
Java代码 
public class Facade { 
 
    /**
     *通过连接操作,提供一个统一的接口,统一跟外界打交道
     *减少对具体实现类的依赖.
     *
     */ 
    public void getConn() { 
        OracleStrategy os = new OracleStrategy(); 
        MysqlStrategy ms =  new MysqlStrategy(); 
        SQLStrategy ss =    new SQLStrategy(); 
 
        os.getConnDB(); 
        ms.getConnDB(); 
        ss.getConnDB(); 
    } 
 
    public static void main(String[] args) { 
         
        new Facade().getConn(); 
    } 

  


      其实JAVA 中的JDBC数据库连接本身也采用了门面模式.
     最后一个想到的模式那就是模板模式.这个就没有代码了,大家可以参考Spring所提供的jdbc抽象框架.其核心就是JDBC模板.可能与最开始的想法偏离,就当是一种发散性思维吧.
      最后来个简单总结吧,主要实现了五种模式:策略模式,代理模式,装饰者模式,门面模式和模板模式.两大原则:开闭原则和迪米特法则.至于两大原则
    策略模式  :主要强调算法的封装和自由切换.
    代理模式  :为其他对象提供一种代理以控制对这个对象的访问.
    装饰者模式:动态添加一个类的功能,实现比继承更灵活的扩展方式.
    门面模式  :系统对外提供一个统一简单的接口,减少系统间的耦合性.
    模板模式  :将代码的公共行为提取出来,达到复用的目的.
讲得比较简单,就当是抛砖引玉.望大家使劲拍砖.
分享到:
评论

相关推荐

    韩顺平_Java设计模式笔记.docx

    "韩顺平_Java设计模式笔记" 本资源摘要信息是对《韩顺平_Java设计模式笔记.docx》的总结和分析,该笔记涵盖了 Java 设计模式的基础知识、设计模式的七大原则、原型设计模式、解释器设计模式、单例设计模式等内容,...

    设计模式笔记(精版)

    以上只是设计模式笔记中的一部分内容,实际上每个模式都有其特定的适用场景和优缺点。理解并熟练运用这些模式,可以提高代码的可读性、可维护性和复用性,降低系统复杂度,提升软件设计的质量。在实际项目中,应根据...

    自己总结的设计模式笔记

    设计模式笔记 设计模式是软件开发中常用的解决方案,能够提高代码的灵活性、可维护性和可扩展性。以下是设计模式的七大原则和两种常用的创建型设计模式。 1. "开-闭"原则 "开-闭"原则是设计模式的核心原则,指...

    设计模式笔记.docx

    设计模式笔记 本文档主要记录了设计模式的笔记,涵盖了UML统一建模语言、用例图、类图、设计模式基本概念、面向对象设计原则、开闭原则等内容。 UML统一建模语言是软件工程中一种标准的建模语言,使用图形化的方法...

    Java设计模式笔记

    以上只是Java设计模式笔记的冰山一角,实际笔记中还会有更多关于每种模式的详细描述、示例代码和应用场景。通过学习和应用这些模式,开发者可以写出更加优雅、可维护的代码,提升团队协作效率和软件质量。

    软件体系结构与设计模式笔记

    软件体系结构与设计模式笔记 软件体系结构是指一个程序或系统的结构,它们之间的相互关系,以及在设计和交付的整个过程中的原则和指导方针。软件体系结构包括构件、连接件和约束三个要素。构件是可预制和可重用的...

    HeadFirst设计模式笔记

    《HeadFirst设计模式笔记》是深入理解软件设计思想的一份宝贵资料,主要涵盖了设计模式的基础理论和实际应用。设计模式是软件开发中的经验总结,它为解决常见的编程问题提供了标准的解决方案,使得代码更具可读性、...

    图解Java设计模式笔记总结word版本.rar

    本资料“图解Java设计模式笔记总结word版本”聚焦于通过图文并茂的方式,深入浅出地解析各种设计模式。以下是基于这个主题的详细知识点讲解: 1. **设计模式的分类** - **创建型模式**:如单例(Singleton)、工厂...

    软件体系结构与设计模式笔记样本.doc

    软件体系结构与设计模式笔记样本 软件体系结构是指软件系统的组织方式和结构,它是软件设计的核心概念。软件体系结构涉及构件、连接件和约束三个要素,构件是可预制和可重用软件部件,是构成体系构造基本计算单元或...

    GOF设计模式笔记

    ### GOF设计模式笔记 #### 一、面向对象设计的基本原则 面向对象设计的原则是指导我们在设计软件系统时遵循的一些准则,这些原则有助于提高代码的可读性、可维护性和可扩展性。 - **SRP (单一职责原则)**: 单一...

Global site tag (gtag.js) - Google Analytics