由MVC引发的对单例模式思考

1.三层架构与MVC模式的区别

三层架构简介

三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。

架构流程图

MVC简介

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

架构流程图

###2. 单例模式有哪些分类

  • 饿汉式单例模式

    饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。

     1 //饿汉式单例
     2 public class Hungry{
     3   //可能会浪费空间
     4   private byte[] data1 = new byte[1024*1024];
     5   private byte[] data2 = new byte[1024*1024];
     6   private byte[] data3 = new byte[1024*1024];
     7   private byte[] data4 = new byte[1024*1024];  
     8   private Hungry(){
     9       
    10   }
    11     private final static Hungry HUNGRY =new Hungry();
    12    
    13     public static Hungry getInstance(){
    14         return HUNGRY;
    15     }
    16 }
    懒汉式单列模式
  • 懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。

     1 public class LazyMan{
     2     private LazyMan(){
     3         
     4     }
     5     private static LazyMan lazyMan;
     6     
     7     //懒汉式单例
     8     public static LazyMan getInstance(){
     9         if(lazyMan==null){
    10             lazyMan =new LazyMan();
    11         }
    12         return lazyMan;
    13     }
    14      /*
    15      * 懒汉式的升级版常用于生产环境
    16      */   
    17 }
    18 静态内部类
    19 
    20 public class Holder{
    21     /*
    22     * 静态内部类绝对安全,无法被反射破解
    23     *
    24     */
    25     private Holder(){
    26     }
    27     public static Holder getInstance(){
    28         return InnerClass.HOLDER;
    29     }
    30     public static class InnerClass{
    31         private static final Holder HOLDER =new Holder()
    32     }
    33 }

3.单例模式是否真的安全

单例模式不安全,可以通过反射来破解

饿汉式和懒汉式单例的区别

1.线程安全

饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,

懒汉式本身是非线程安全的,为了实现线程安全有几种写法。

例如:

 1 import com.sun.corba.se.impl.orbutil.CorbaResourceUtil; 
 2 import java.lang.reflect.Constructor; 
 3 import java.lang.reflect.Field;
 4 //懒汉式升级单例
 5 public class LazyManPlus{
 6     
 7     private LazyManPlus(){
 8         synchronized (LazyMan.class){
 9             if (LMJ == false){ 
10                 LMJ = true; 
11             }else { 
12                 throw new RuntimeException("不要试图使用反射破坏异常"); 
13             }
14     }
15     }
16     //volatile  保证可见性,保证原子有序性,避免指令重排,不保证原子性
17     private  volatile  static LazyManPlus lazyManPlus;
18     private static LazyManPlus getInstance(){
19    if (lazyMan==null){
20        synchronized (LazyMan.class){ 
21            if (lazyMan==null){ 
22            lazyMan = new LazyMan(); // 不是一个原子性操作 } }
23             }
24        }
25         return lazyManPlus;
26     }
27     //反射!
28     public static void main(String[] args){
29         
30         Field LMJ = LazyManPlus.class.getDeclaredField("LMJ");//自定义一个名字,监测
31         LMJ.setAccessible(true);//将私有类打开,破解成功
32         Constructor<LazyMan> declaredConstructor =                                            LazyMan.class.getDeclaredConstructor(null);                                         declaredConstructor.setAccessible(true); 
33         LazyMan instance = declaredConstructor.newInstance();
34         LMJ.set(instance,false);
35         LazyMan instance2 = declaredConstructor.newInstance();           
36         System.out.println(instance);
37         System.out.println(instance2);
38     }
39 }

2.资源加载和性能

饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。

而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

注:单例模式能够被反射破解,枚举类不能被破解

1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.InvocationTargetException;
3 // enum 是一个什么? 本身也是一个Class类 
4 public enum EnumSingle 
5 {  INSTANCE; 
6  public EnumSingle getInstance(){
7      return INSTANCE; 
8  } 
9 }

4.java中的反射

简单理解

Java编写的程序,一次编译,到处运行。这也是Java程序为什么是无关平台的所在,原因在于,java的源代码会被编译成.class文件字节码,只要装有Java虚拟机JVM的地方(Java提供了各种不同平台上的虚拟机制,第一步由Java IDE进行源代码编译,得到相应类的字节码.class文件,第二步,Java字节码由JVM执行解释给目标计算机,第三步,目标计算机将结果呈现给我们计算机用户;因此,Java并不是编译机制,而是解释机制),.class文件畅通无阻。主要操作.class文件

Java的反射机制,操作的就是这个.class文件,首先加载相应类的字节码(运行eclipse的时候,.class文件的字节码会加载到内存中),随后解剖(反射 reflect)出字节码中的构造函数、方法以及变量(字段),或者说是取出

5.三层架构是如何体现高内聚、低耦合的开发思想

1.封装每一层的接口,采用面向对象的接口封装思想

2.分层调用接口,每一层的接口互不联系,达到低耦合的思想

3.每个接口具有一个实现类,体现高内聚,即对高内聚

4.对外只开发一个接口

6.java中的泛型的作用

泛型定义的语法如下:

[访问修饰符] class 类名称 <T>

代码演示

 1 public class Base<T> {
 2   T m;
 3   Base(T t) {
 4     m = t;
 5   }
 6   public T getM(){
 7     return m;
 8   }
 9   public void print() {
10     System.out.println("base print : " + m);
11   }
12   public static void main(String[] args) {
13     Base<String> base=new Base<String>("base class is general");
14     System.out.println(base.getM());
15     base.print();
16   }
17 }

T可以用任何一种引用类型,但是不允许使用基本类型,如int、double、char、boolean等是不允许的。泛型类定义时,可以使用T来定义其成员变量和成员方法的返回值和参数。

泛型方法主要用于容器类,Java中任何方法,包括静态的(注意,泛型类不允许在静态环境中使用)和非静态的,均可以用泛型来定义,而且和所在类是否是泛型没有关系。

使用泛型方法时,至少返回值或参数有一个是泛型定义的,而且应该保持一致,否则可能会受到各种限制,因此,这里建议保持一致。

7.JQuery中的$.ajax语法

$.ajax({
   type: "POST",
   url: "some.php",
   data: "name=John&location=Boston",
   success: function(msg){
     alert( "Data Saved: " + msg );
   }
});

String serialize() 函数

序列表表格内容为字符串,用户Ajax请求。将JSON数据转化为String类型

例如:HTML代码

 1 <p id="results"><b>Results: </b> </p>
 2 <form>
 3   <select name="single">
 4     <option>Single</option>
 5     <option>Single2</option>
 6   </select>
 7   <select name="multiple" multiple="multiple">
 8     <option selected="selected">Multiple</option>
 9     <option>Multiple2</option>
10     <option selected="selected">Multiple3</option>
11   </select><br/>
12   <input type="checkbox" name="check" value="check1"/> check1
13   <input type="checkbox" name="check" value="check2" checked="checked"/> check2
14   <input type="radio" name="radio" value="radio1" checked="checked"/> radio1
15   <input type="radio" name="radio" value="radio2"/> radio2
16 </form>
//JQuery代码
$("#results").append( "<tt>" + $("form").serialize() + "</tt>" );
 

猜你喜欢

转载自www.cnblogs.com/blogger-Li/p/12424886.html