如何基于Spring使用工厂模式实现程序解耦

这篇文章主要介绍了如何基于Spring使用工厂模式实现程序解耦,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

1、 啥是耦合、解耦?

既然是程序解耦,那我们必须要先知道啥是耦合,耦合简单来说就是程序的依赖关系,而依赖关系则主要包括

1、 类之间的依赖

2、 方法间的依赖

比如下面这段代码:

 public class A{
    public int i;
  }

  public class B{
    public void put(A a){
      System.out.println(a.i);
    }
  }

上面这个例子中A类和B类之间存在一种强耦合关系,B类直接依赖A类,B类的put方法非A类类型不可,我们把这种情况叫做强耦合关系。

实际开发中应该做到:编译期不依赖,运行时才依赖。怎么理解呢?我们很容易想到多态向上转型,是的,编译时不确定,运行时才确定,当然接触面更广一点的童鞋会想到接口回调,是的接口回调方式也能有效的解耦!如下代码:

//一个接口叫做Inter,里面定义了一个happy()方法,有两个类A、B实现了这个接口

interface Inter{
  void happy();
}

class A implements Inter{

  @Override
  public void happy() {
    System.out.println("happy...A");
  }
}

class B implements Inter{

  @Override
  public void happy() {
    System.out.println("happy...B");
  }
}

public class Test{
  public void happys(Inter inter){
    inter.happy();
  }
}

是的,如上代码正是典型的接口回调,Test类中的happys方法参数变的相对灵活起来,代码中Test类与A类、B类之间就存在一种弱耦合关系,Test类的happys方法的参数可以使A类类型也可以是B类类型,不像强耦合关系中非A类类型不可的情形。

从某一意义上来讲使用类的向上转型或接口回调的方式进行解耦都是利用多态的思想!

当然解耦的方式还有很多,从根本意义上讲实现低耦合就是对两类之间进行解耦,解除类之间的直接关系,将直接关系转换成间接关系,从而也有很多设计模式也对程序进行解耦,比如:适配器模式、观察者模式、工厂模式....总之,必须明确一点:耦合性强的程序独立性很差!

2、 jdbc程序进行解耦

先来看一段代码:

//1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //如果把jdbc的MySQLjar包依赖去除直接编译失败提示没有mysql
//2、获取连接
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/ufida","root","root");
//3、获取操作数据库的预处理对象
PreparedStatement pstm=conn.prepareStatement("select * from client");
//4、执行SQL,得到结果集
ResultSet rs=pstm.executeQuery();
//5\遍历结果集
while(rs.next()){
  System.out.println(rs.getString("name"));
}
//6、释放资源
rs.close();
pstm.close();
conn.close();

等等等等,好熟悉好怀念的代码.....

没错就是jdbc的代码,不是用来怀旧的,而是如果这样设计,你会觉得这样的程序耦合性如何?又如何进行解耦?先仔细思考一番。

一分钟过去了.....

两分钟过去了.....

好了,我们都知道jdbc连接MySQL需要一个mysql-connector的jar包,如果我们把这个jar包依赖或者这个jar包给去掉,显然上面的这个程序会编译报错,如下图

显然这样的程序耦合性过高!于是我们可以这样设计,将第一步的注册驱动代码new的方式改成反射的方式如下:

 //1、new的方式注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //如果把jdbc的MySQLjar包依赖去除直接编译失败提示没有mysql相关的jar包

改为如下方式

 //2、反射的方式注册驱动
Class.forName("com.mysql.jdbc.Driver"); //改用这种方式注册驱动会发现不会编译失败,相比上面的方式相对解耦,但是依然存在缺陷:若连接改为Oracle数据库,这里的字符串又要进行改动!

正如注释的解释一样,又一个缺陷就浮现了:若连接改为Oracle数据库,这里的字符串又要进行改动!

于是对于这个jdbc程序来说就有这样的一个解耦思路:

第一步:通过反射来创建对象,尽量避免使用new关键字

第二步:通过读取配置文件来获取创建的对象全限定类名

3、传统dao、service、controller的程序耦合性

顺着jdbc程序的解耦思路,我们再来看看传统dao、service、controller的程序耦合性分析

由于只是一个demo,省去dao层的操作.....

定义一个Service接口

public interface IAccountOldService{
  public void save();
}

Service接口实现类

public class AccountServiceOldImpl implements IAccountOldService{
  @Override
  public void save() {
    System.out.println("save成功一个账户....");
  }
}

controller代码:

public class AccountCencollertOld {
  public static void main(String[] args) {
    IAccountOldService iaccount=new AccountServiceOldImpl ();
    iaccount.save(); //运行结果:save成功一个账户....
  }
}

到这里,有何想法?表面上来看是没有一点问题的,So Beautiful,但仔细的看。表现层与业务层、业务层与持久层紧紧的互相依赖关联,这与我们开发程序的高内聚低耦合原则相违背,哦My God,So Bad!我们顺着jdbc程序的解耦思路,我们应该尽量避免使用new关键字,我们发现这些层里面service层new 持久层dao,controller表现层new 业务层service....太糟糕了

那么对此,你有何解耦思路?

4、使用工厂模式实现解耦

别想了,工厂模式实现程序解耦你值得拥有!顺着jdbc程序的解耦思路:

1、通过读取配置文件来获取创建的对象全限定类名
2、通过反射来创建对象,尽量避免使用new关键字

首先在resources目录下中写一个bean.properties配置类,具体内容如下

accountServiceOld=com.factory.service.impl.AccountServiceOldImpl

接着使用工厂方法代码:

/**
 * 一个创建Bean对象的工厂
 *
 *  1、需要一个配置文件来配置我们的service和dao  配置文件的内容:唯一标识=全限定类名(key-value)
 *  2、通过读取配置文件中配置的内容,反射创建对象
 *
 *  场景:主要是service调用dao,controller调用service的程序。这里面耦合性非常的高,互相new互相依赖
 *
 *  为了解耦,利用工厂模式进行
 */
 public class BeanFactoryOld {
  private static Properties props;

  static{
    try {
      //实例化对象
      props = new Properties();

      //获取properties文件的流对象
      InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
      props.load(in);//加载其对应路径下的配置文件

    }catch (Exception e){
      throw new ExceptionInInitializerError("初始化properties失败!");
    }
  }

  //根据bean的名称获取bean对象
  public static Object getBean(String beanName){
    Object bean=null;
    try {
    String beanPath= props.getProperty(beanName);
    bean = Class.forName(beanPath).newInstance();  //这里的newInstance创建实例(默认无参构造器)每次执行都需要创建一次
    } catch (Exception e) {
      e.printStackTrace();
    }
    return bean;
  }
}

此时,controller的代码就可以编写为

/**
 * 这里模拟一个controller调用service
 *
 */
public class AccountCencollertOld {
  public static void main(String[] args) {
  //  IAccountOldService iaccount=new AccountServiceOldImpl (); //使用工厂方法不再通过new方式

    IAccountOldService iaccount= (IAccountOldService) BeanFactoryOld.getBean("accountServiceOld");
    iaccount.save(); //运行结果:save成功一个账户....  说明成功调用了service
  }
}

通过运行结果,属实没毛病,成功降低程序耦合!So Beautiful!先高兴一会吧,因为马上出现.....但是,随之而来的问题又出现了,我们对这个controller进行一下改写

for(int i=0;i<5;i++){
    IAccountOldService iaccount= (IAccountOldService) BeanFactoryOld.getBean("accountServiceOld");
    iaccount.save();
   }

打印结果:

com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
com.factory.service.impl.AccountServiceImpl@677327b6
save成功一个账户....
com.factory.service.impl.AccountServiceImpl@14ae5a5
save成功一个账户....
com.factory.service.impl.AccountServiceImpl@7f31245a
save成功一个账户....
com.factory.service.impl.AccountServiceImpl@6d6f6e28
save成功一个账户....

打印的是五个不同的对象,说明是多例的,每次调用getBean的时候都会newInstance出一个新对象,如下

多例每次都要创建对象,资源浪费、效率低下

针对单例多例情况,我们再对service业务层代码进行修改:

public class AccountServiceImpl implements IAccountService {
  //定义类成员
  private int i=1; 

  @Override
  public void save() {
    System.out.println("save成功一个账户....");
    System.out.println(i);
    i++;
  }
}

运行controller代码,运行结果

save成功一个账户....
1
save成功一个账户....
1
save成功一个账户....
1
save成功一个账户....
1
save成功一个账户....
1

why?多例因为每次都是新的对象,上面也验证过了,因此每次创建新对象都会初始化一次,重新赋值,所以都是1,如果我们把类成员改为局部成员变量如下

public class AccountServiceOldImpl implements IAccountOldService {

//  private int i=1;
  @Override
  public void save() {
    int i=1;  //改为局部变量
    System.out.println("save成功一个账户....");
    System.out.println(i);
    i++;
  }
}

不用猜,运行结果同样是1。算了还是运行一下吧哈哈哈

save成功一个账户....
1
save成功一个账户....
1
save成功一个账户....
1
save成功一个账户....
1
save成功一个账户....
1

说了这么多,通过观察service和dao之间单不单例好像无所谓,因为他们之间并没有业务方法中改变的类成员,所以并不需要多例来保证线程安全。那说这些有何意义?不要忘了,由于使用了工厂改进如下中的.newInstance创建实例(默认无参构造器)每次执行都需要创建一次,这样就不好了(浪费资源),因此我们要设计出只newInstance创建一次实例就很完美了,这也是我为啥要在service和controller中都添加一个Old关键字的原因了,接下来我们来看看工厂是如何改进的!

5、工厂模式改进

为了不被搞晕,我们重新写代码,也就是重头开始写代码~其实就是把Old去掉~

由于只是一个demo,省去dao层的操作.....

定义一个Service接口

public interface IAccountService {
  public void save();
}

Service接口实现类

public class AccountServiceImpl implements IAccountService{

  @Override
  public void save() {
    System.out.println("save成功一个账户....");
  }
}

controller代码:

/**
 * 这里模拟一个controller调用service
 *
 */
public class AccountCencollert {
  public static void main(String[] args) {
//    IAccountService iaccount=new AccountServiceImpl(); 

    IAccountService iaccount= (IAccountService) BeanFactory.getBean("accountService");
    iaccount.save(); //运行结果:save成功一个账户....  说明了成功调用了service
   }
 }

改进的工厂方法代码:

public class BeanFactory {
  private static Properties props;

  //定义一个map容器,用于存放创建的对象
  private static Map<String,Object> beans; //改进的代码============

  static{
    try {
      //实例化对象
      props = new Properties();

      //获取properties文件的流对象
      InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
      props.load(in);//加载其对应路径下的配置文件

      ////////////////////以下是改进的代码=======================
      //实例化容器
      beans=new HashMap<String,Object>();
      //取出配置文件中所有的key值
      Enumeration<Object> keys = props.keys();
      //遍历枚举
      while(keys.hasMoreElements()){
        //取出每个key
        String key = keys.nextElement().toString();
        //根据key取出对应的value (这里因为每个value值对应着类路径)
        String beanPath = props.getProperty(key);
        //反射创建对象
        Object value = Class.forName(beanPath).newInstance();
        //把key和value存入容器中
        beans.put(key,value);
      }
    }catch (Exception e){
      throw new ExceptionInInitializerError("初始化properties失败!");
    }
  }

  //随着代码的改进,我们就可以简化下面的获取bean对象的方法,如下代码
  /**
   * 根据bean的名称获取对象(单例)
   */
  public static Object getBean(String beanName){
    //通过Map容器对应key来获取对应对象
    return beans.get(beanName);  //这里通过Map容器中获取,这样就不会每次都创建一次实例!
  }

//不再使用下面的方法
 /*
  //根据bean的名称获取bean对象
  public static Object getBean(String beanName){
    Object bean=null;
    try {
    String beanPath= props.getProperty(beanName);
    bean = Class.forName(beanPath).newInstance();  //这里的newInstance创建实例(默认无参构造器)每次执行都需要创建一次,这样就不好了
    } catch (Exception e) {
      e.printStackTrace();
    }
    return bean;
  }*/
}

从上面改进的工厂代码,我们可以发现一开始就定义一个Map容器,用于存放创建的对象,为啥要先定义一个Map容器呢?用一个容器将这个实例装起来,这是由于不把这个对象装存起来的话,这个对象不使用很容易被GC掉,何况我们现在只使用这一个对象!

定义一个Map容器存放配置好的文件中的每个对象,之后我们就直接提供一个根据Map的key来取value的getBean方法,这样不仅仅扩展了程序的配置文件的灵活性而且还保证了只产生一个对象,保证资源不浪费,So Beautiful !

那如何证明已经是单例的模式了呢?很简单,如下设计一下service业务层、controller表现层代码即可:

service业务层:添加一个类成员属性,并在方法内部 i++;

public class AccountServiceImpl implements IAccountService {

  private int i=1; //类成员属性

  @Override
  public void save() {
    System.out.println("save成功一个账户....");
    System.out.println(i);
    i++;//二次改革代码
  }
}

controller表现层: 创建调用工厂5次创建对象的方法

/**
 * 这里模拟一个controller调用service
 *
 */
public class AccountCencollert {
  public static void main(String[] args) {
    for(int i=0;i<5;i++){
      IAccountService iaccount= (IAccountService) BeanFactory.getBean("accountService");
      System.out.println(iaccount); //打印的是五个不同的对象,说明是多例的
      iaccount.save(); //会发现打印的i值都是1,并没有自增成功
    }
  }

运行代码结果:

com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
1
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
2
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
3
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
4
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
5

发现,确实5个对象都是同一个,并且出现了改变类成员属性的现象。

如果我们把类成员属性改为局部成员属性呢?

public class AccountServiceImpl implements IAccountService {

  @Override
  public void save() {
    int i=1; //局部成员属性
    System.out.println("save成功一个账户....");
    System.out.println(i);
    i++;
  }
}

运行结果

com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
1
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
1
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
1
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
1
com.factory.service.impl.AccountServiceImpl@1540e19d
save成功一个账户....
1

看到这个结果,我们就能联想到,之前为什么servlet中为啥要避免定义类成员,原因就在这里!多例情况下,就不会出现这种情况!!!!

6、结语

到这里我们已经基本了解了程序间的耦合与解耦,并且对单例多例也一并进行了进一步的了解。而spring中正是使用工厂模式来实现程序解耦的,spring是一个大工厂, 或许你并没有察觉哈哈哈哈.....

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用spring的IOC解决程序耦合的方法

    在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来.在接下来的使用的时候,直接拿过来用就好了. 那么,这个读取配置文件,创建和获取三层对象的类就是工厂. 简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式.在简单工厂模式中,可以根据参数的不同返回不同类的实例.简单工厂模式专门定义一个类来负责创建其他类的实

  • Spring实战之使用静态工厂方法创建Bean操作示例

    本文实例讲述了Spring实战之使用静态工厂方法创建Bean操作.分享给大家供大家参考,具体如下: 一 配置 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" x

  • 微信小程序 springboot后台如何获取用户的openid

    openid可以标识一个用户,session_key会变,所以来获取一下openid. openid不能在微信小程序中直接获取,需要后台发送请求到微信的接口,然后微信返回一个json格式的字符串到后台,后台处理之后,再返回到微信小程序. 发布的小程序需要https的域名,而测试的时候可以使用http. 小程序在app.js中,修改login()中的内容: // 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, session

  • 使用spring工厂读取property配置文件示例代码

    本文将介绍两种Spring读取property配置文件的方法,接下来看看具体内容. 一.通过Spring工厂读取 示例: public class PropertyConfig { private static AbstractBeanFactory beanFactory = null; private static final Map<String,String> cache = new oncurrentHashMap<>(); @Inject public Property

  • Spring的实例工厂方法和静态工厂方法实例代码

    Spring的实例工厂方法和静态工厂方法都可以用来实例化bean,本文我们就来看看相关实例. 静态工厂方法:直接调用静态方法可以返回Bean的实例 package com.zhu.string.factory; import java.util.HashMap; import java.util.Map; public class StaticCarFactory { /** * 静态工厂方法:直接调用静态方法可以返回Bean的实例 * */ private static Map<String

  • java Spring松耦合高效应用简单实例分析

    java Spring松耦合 面向对象的概念,是一个很好的设计来打破系统进入一个组可重用的对象.然而,当系统变大,尤其是在Java项目,庞大的对象依赖关系将一直紧密耦合引起对象难以管理或修改.在这种情况下,可以使用Spring框架作为一个核心模块轻松高效地管理所有的对象依赖. 输出生成器的例子 让我们来看一个例子,假设你的项目有一个函数输出的内容,以CSV或JSON格式.您的代码可能看起来像下面的例子: File : IOutputGenerator.java – 输出生成器接口 package

  • Linux 启动停止SpringBoot jar 程序部署Shell 脚本的方法

    废话不多说了,先给大家上代码,具体代码如下所示: #!/bin/bash cd `dirname $0` CUR_SHELL_DIR=`pwd` CUR_SHELL_NAME=`basename ${BASH_SOURCE}` #修改这里jar包名即可 JAR_NAME="xxxxxxxxxxxx.jar" JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME #JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:Pe

  • Spring实战之调用实例工厂方法创建Bean操作示例

    本文实例讲述了Spring实战之调用实例工厂方法创建Bean操作.分享给大家供大家参考,具体如下: 一 配置 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" x

  • Spring工厂方法创建(实例化)bean实例代码

    目标明确 简单叙述一下本文想要解决的问题:如何在Spring中不再使用Spring创建Bean实例,而是把Bean创建过程转移到开发者手中. 思路清晰 创建Bean实例的方式: 1) 通过构造器(有参或无参) 方式: <bean id="" class=""/> 2) 通过静态工厂方法 方式: <bean id="" class="工厂类" factory-method="静态工厂方法"/

  • 如何基于Spring使用工厂模式实现程序解耦

    这篇文章主要介绍了如何基于Spring使用工厂模式实现程序解耦,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1. 啥是耦合.解耦? 既然是程序解耦,那我们必须要先知道啥是耦合,耦合简单来说就是程序的依赖关系,而依赖关系则主要包括 1. 类之间的依赖 2. 方法间的依赖 比如下面这段代码: public class A{ public int i; } public class B{ public void put(A a){ System.o

  • 基于Spring Boot保护Web应用程序

    如果在类路径上添加了Spring Boot Security依赖项,则Spring Boot应用程序会自动为所有HTTP端点提供基本身份验证.端点"/"和"/home"不需要任何身份验证.所有其他端点都需要身份验证. 要将Spring Boot Security添加到Spring Boot应用程序,需要在构建配置文件中添加Spring Boot Starter Security依赖项. Maven用户可以在pom.xml 文件中添加以下依赖项. <depend

  • 详解使用Spring的BeanPostProcessor优雅的实现工厂模式

    最近学习Spring的源码,发现一个利器BeanPostProcessor.这个后置处理器可以在bean初始化前后对bean进行操作.我们可以在初始化的时候对自己想要的bean进行缓存,进而实现自己需要处理的逻辑. 背景 当我们需要根据类型调用接口不同实现的时候,我们可以使用工厂模式实现.下面说下博主遇到过的两次需要使用工厂的场景. 场景一: 当有一个模块,我们需要根据数据库的类型实现不同的的sql.我们此时需要定义一个接口然后每一种数据库实现不同的sql.在调用时根据当前的数据库类型调用对应的

  • 轻松掌握Java工厂模式、抽象工厂模式

    在面向对象编程的程序设计中,我们最常见的操作就是new对象,但在创建一个新对象的过程中,会有一些问题,比如我们需要注意创建新对象的实现细节,初始化一些必要的参数等.这样会让我们在讲更多的心思放在对象的创建上,而不是程序逻辑的实现上,严重拖延了我们的程序开发效率.工厂模式和抽象工厂模式的出现则完美解决了这个问题,让我们不再关心对象的创建,更多的在重心放在业务的实现上. 特点: 1.程序员直接通过工厂方法创建对象,不再关注创建对象的细节. 2.隐藏对象的实现细节,也有利于程序的安全性. 3.降低程序

  • 实例解析C++设计模式编程中简单工厂模式的采用

    简单工厂模式中专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类.它又称为静态工厂方法模式,属于类的创建型模式. 简单工厂模式的UML类图 简单工厂模式的程序通过封装继承来降低程序的耦合度,设计模式使得程序更加的灵活,易修该,易于复用. 简单工厂是在工厂类中做判断,从而创造相应的产品. 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例.   该模式中包含的角色及其职责   1.工厂(Creator)角色  

  • 一篇文章带你入门java工厂模式

    目录 总结: Java设计模式-工厂模式 什么是工厂模式? 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象. 简单编写一个类: 1.简单工厂模式 本程序非常简单就是通过接口的子类为接口对象实例化,但是本操作存在什么样的问题呢? 之前一直在强调,主方法或者是主类是一个客户端,客户端的操作应该越简单

  • C#基于简单工厂模式实现的计算器功能示例

    本文实例讲述了C#基于简单工厂模式实现的计算器功能.分享给大家供大家参考,具体如下: 子类拥有父类除私有之外的所有属性字段和方法 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 工厂方法实现计算器 { /// <summary> /// 计算器类(抽象类,由子类重写) /// </sum

  • PHP基于工厂模式实现的计算器实例

    本文实例讲述了PHP基于工厂模式实现的计算器.分享给大家供大家参考.具体如下: abstract class Calculator { private $number1; private $number2; public $result; /** * @return the $number2 */ public function getNumber2() { return $this->number2; } /** * @param field_type $number2 */ public f

  • 基于php设计模式中工厂模式详细介绍

    工厂模式:由工厂类根据参数来决定创建出哪一种产片类的实例工厂类:一个专门用来创建其他对象的方法类.即按需分配,传入参数进行选择,返回具体的类作用:对象创建的封装.简化创建对象的操作,即调用工厂类的一个方法来得到需要的类补充:1.主要角色:抽象产品(Product).具体产品(Concrete Product).抽象工厂角色(Creator)2.优缺点    优点:工厂方法模式可以允许系统在不修改工厂角色的情况下引进心产品    缺点:客户可能仅仅为了创建一个特定的Concrete Product

  • 基于Spring + Spring MVC + Mybatis 高性能web构建实例详解

    一直想写这篇文章,前段时间痴迷于JavaScript.NodeJs.AngularJS,做了大量的研究,对前后端交互有了更深层次的认识. 今天抽个时间写这篇文章,我有预感,这将是一篇很详细的文章,详细的配置,详细的注释,看起来应该很容易懂. 用最合适的技术去实现,并不断追求最佳实践.这就是架构之道. 希望这篇文章能给你们带来一些帮助,同时希望你们可以为这个项目贡献你的想法. 源码地址:https://github.com/Eliteams/quick4j 点击打开 源码地址:https://gi

随机推荐