zoukankan      html  css  js  c++  java
  • Spring轻量级开发---基础知识和初体验

    1.首先先来看看最简单的hello world程序

    public static void main(String[] args){    
        System.out.println("HelloWorld");
    }

    2.如果需要修改输出的字符串的内容,需要重新编译代码和测试相关联的功能,这是很不合理和危险的。一个更好的解决方案是让程序接收外部消息字串,这样就可以在运行时决定输出的内容。

    public static void main(String[] args){
        if(args.length>0)
            System.out.println(args[0]);
        else
            System.out.println("HelloWorld");
    }

    3.这样的修改可以让我们改变输出的字串,这是一个进步。但观察这个程序,有两个功能:取得外部参数、输出字串

    这两个功能被捆绑在一起,这是过程化的思维方式。所以我们需要分离职责

    为了使程序的架构更灵活,我们应该将这两个职责装入不同的组件里,可以使用接口来实现两个不同的职责。而主程序main只和这两个组件接口打交道。

    首先建两个接口

     1 public interface IMessageDisplayer {
     2     /**
     3      * 消息显示者接口
     4      */
     5     void display();
     6     
     7     /**
     8      * 
     9      * 提供get/set方法
    10      */
    11     void setIMessageSupplier(IMessageSupplier s);
    12     IMessageSupplier getIMessageSupplier();
    13 }
    1 public interface IMessageSupplier {
    2     /**
    3      * 取得消息
    4      */
    5     String getMessage();
    6 }

    然后分别给出这两个类的实现

     1 public class HelloWorldDisplayer implements IMessageDisplayer {
     2 
     3     private IMessageSupplier messageSupplier=null;
     4     
     5     public void display() {
     6         if(null==messageSupplier){
     7             throw new RuntimeException("messageSupplier为空");
     8         }
     9         System.out.println(messageSupplier.getMessage());
    10     }
    11 
    12     public IMessageSupplier getIMessageSupplier() {
    13         return messageSupplier;
    14     }
    15 
    16     public void setIMessageSupplier(IMessageSupplier s) {
    17         this.messageSupplier=s;
    18     }
    19 }
    1 public class HelloWorldSupplier implements IMessageSupplier{
    2     public String getMessage(){
    3         return "HelloWorldSup";
    4     }
    5 }

    然后重构下主程序即可

     1 public class HelloWorldBetter {
     2     /**
     3      * 初步重构HelloWorld之后的主程序体
     4      * 解耦了消息显示者和消息提供者这两个职责
     5      */
     6     public static void main(String[] args) {
     7         //创建消息显示者
     8         IMessageDisplayer messageDisplayer=new HelloWorldDisplayer();
     9         //创建消息提供者
    10         IMessageSupplier messageSupplier=new HelloWorldSupplier();
    11         //注入消息提供者
    12         messageDisplayer.setIMessageSupplier(messageSupplier);
    13         //显示消息
    14         messageDisplayer.display();
    15     }
    16 }

    4.经过这样重构后,我们的成果已经比较成功了。但仍存在一些问题,如果想替换接口的实现类,则依然需要在程序中手动改动代码,那么程序代码依然要经历重新编译测试的风险,为了克服这一缺点,可以引入单例工厂(Singleton Factory)

    我们首先创建一个单例工厂类

     1 /**
     2  * Message组件生产工厂,这是一个单例类
     3  * 通过读取外部属性文件msgbean.properties
     4  * 获取MessageDisplayer和MessageSupplier的实现类名
     5  * 并由工厂创建各自的实例
     6  */
     7 public class MessageSupporterFactory {
     8 
     9         /**
    10          * 全局单一的工厂实例 注意需要静态
    11          */
    12         private static MessageSupporterFactory factory=null;
    13         
    14         /**
    15          * 外部属性
    16          */
    17         private static Properties props;
    18         
    19         /**
    20          * 创建MessageSupportFactory单例方法
    21          * 使用Synchronized保障线程安全
    22          */
    23         public synchronized static MessageSupporterFactory getInstance()   {
    24             if(factory==null)
    25                 factory=new MessageSupporterFactory();
    26             return factory;
    27         }
    28         private MessageSupporterFactory(){
    29             props=new Properties();
    30             try{
    31                 props.load(new FileInputStream("conf/ch2/msgbean.properties"));
    32             }catch(Exception e){
    33                 e.printStackTrace();
    34             }
    35         }
    36         
    37         /**
    38          * 产生IMessageDisplayer的工厂方法
    39          */
    40         public IMessageDisplayer makeMessageDisplayer(){
    41             //读取IMessagePlayer具体的实现名字
    42             String displayClass=props.getProperty("display.class");
    43             try {
    44                 return (IMessageDisplayer)Class.forName(displayClass).newInstance();
    45             } catch (InstantiationException e) {
    46                 System.out.println("can not instantiate an object of type "+displayClass);
    47                 e.printStackTrace();
    48             } catch (IllegalAccessException e) {
    49                 System.out.println("can not access class "+displayClass);
    50                 e.printStackTrace();
    51             } catch (ClassNotFoundException e) {
    52                 System.out.println("can not find the class "+displayClass);
    53                 e.printStackTrace();
    54             }
    55             return null;
    56         }
    57         
    58         /**
    59          * 产生IMessageSupplier的工厂方法
    60          */
    61         public IMessageSupplier makeMessageSupplier(){
    62             //读取IMessageSupplier具体的实现名字
    63             String supplyClass=props.getProperty("supply.class");
    64             try {
    65                 return (IMessageSupplier)Class.forName(supplyClass).newInstance();
    66             } catch (InstantiationException e) {
    67                 System.out.println("can not instantiate an object of type "+supplyClass);
    68                 e.printStackTrace();
    69             } catch (IllegalAccessException e) {
    70                 System.out.println("can not access class "+supplyClass);
    71                 e.printStackTrace();
    72             } catch (ClassNotFoundException e) {
    73                 System.out.println("can not find the class "+supplyClass);
    74                 e.printStackTrace();
    75             }
    76             return null;
    77         }
    78 }

    然后只要创建properties文件即可。

    display.class=ch2.HelloWorldDisplayer;
    supply.class=ch2.HelloWorldSupplier;

    现在只需要稍微修改一下主程序main就可以达到预期效果了。

     1 public class HelloWorldBetterWithFactory {
     2     public static void main(String[] args) {
     3         //创建消息显示者
     4         IMessageDisplayer messageDisplayer=MessageSupporterFactory.getInstance().makeMessageDisplayer();
     5         //创建消息提供者
     6         IMessageSupplier messageSupplier=MessageSupporterFactory.getInstance().makeMessageSupplier();
     7         //注入消息提供者
     8         messageDisplayer.setIMessageSupplier(messageSupplier);
     9         //显示消息
    10         messageDisplayer.display();
    11     }
    12 }

    程序中通过读取配置文件获得类名,并通过反射获取类的实例,从而实现输出的目的。尽管一个hello world程序不需要这么繁琐地做修改,但其中的道理却很有用: 为避免程序重新编译测试的风险,我们应该尽量把程序的责任分离,降低耦合度。而工厂模式和反射则是一个降低耦合度的很好用的方法。

  • 相关阅读:
    STL中的map
    HDU 4027 Can you answer these queries?
    HDU 2199 Can you solve this equation?
    USACO section1.2 Name That Number 命名那个数字
    HDU 3790 最短路径问题 (双重权值)
    [笔记]CiscoPT配置RIP
    [笔记]Cisco PT VLANTrunk配置
    iptables感悟Ubuntu
    CentOS网络配置
    Discuz X2 数据库备份功能分析
  • 原文地址:https://www.cnblogs.com/elenno/p/SpringTest.html
Copyright © 2011-2022 走看看