- 浏览: 373507 次
- 性别:
- 来自: 青岛
文章分类
最新评论
-
lippeng:
楼主,你好!这篇中提到的一个话题,是我现在非常关心的,我自己还 ...
使用JUnit测试通过 HttpClient(https协议)访问支付宝接口时不能自动获得证书的解决办法 -
snoopy7713:
[2014-03-14 17:55:06.651] TCP ...
刚完成Struts的Virgo插件,分享一下设计思路和Virgo OSGi内部的独特机制 -
snoopy7713:
需要看一下,你的代码说的挺模糊的。我的联系方式QQ 16200 ...
刚完成Struts的Virgo插件,分享一下设计思路和Virgo OSGi内部的独特机制 -
roronjavaeye:
不错,受教了
java_class反编译后的代码还原 -
daoyongyu:
讲的很好,很详细。
Struts2配置文件详解——struts.properties
简而言之,在我们处理大量问题时,在很多不同的问题中重复出现的一种性质,它使得我们可以使用一种方法来描述问题实质并用本质上相同,但细节永不会重复的方法去解决,这种性质就叫模式。模式化过程是把问 题抽象化,在忽略掉不重要的细节后,发现问题的一般性本值,并找到普遍使用的方法去解决的过程。
发现模式是与研究模式同时发生的,发现一个新的模式很不容易。一个好的模式必须满足以下几点:
1、它可以解决问题。模式不能仅仅反映问题,而必须对问题提出解决方案。
2、它所提出解决方案是正确的,而且不是很明显的。
3、它必须是涉及软件系统深层的结构的东西,不能仅是对已有的模块的描述。
4、它必须满足人的审美,简洁美观。
换言之,一个美妙的东西不一定就是模式,但是一个模式必须是一个美妙的东西。
软件工程学的各个方面,诸如开发组织,软件处理,项目配置管理,等等,都可以看到模式的影子。但至今 得到了最好的研究的是设计模式和组织模式。在软件编程中使用模式化方法, 是在编程对象化之后才开始得到重视的。软件编程中模式化方法的研究,也是在九十年代才开始。
在面向对象的编程中使用模式化方法研究的开创性著作,是
Design Patterns - Elements of Reusable Object-Oriented Software, E.Gamma, R. Helm, R. Johnson, and J. Vlissides,1995, Addison-Wesley.
这四位作者通常被称为四人帮(Gang of Four, 或GoF)。(在这个词出现以后,很多西方商业炒作利用这个 路人皆知的词赚钱,有一个八十年代的美国四人乐队以此为队名。在英国政界更曾有好几个小帮派被称为四人帮。 在这里大家使用这个词称呼这四个著名作者,带有戏虐成分。)
由于爪哇语言的特点,使得模式在爪哇语言的实现有自己的特点。 爪哇语言是现今最普及的纯粹OOP的编程语言,使用爪哇语言编程的程序师平均的素质也相对比较高。 这些程序师往往不满足于只是实现程序功能要求,他们常常想要在代码结构,编程风格,乃至解决问题的 思考方式上不断进取和自我完善。模式,就是在大量的实践中总结和理论化之后的优选的代码结构,编程风格, 及解决问题的思考方式。对模式的了解和掌握,是爪哇程序师提高自身素质的一个很好的方向。
作者在学习和工作中把自己的体会 总结下来,藉以与读者交流提高。
作者在后面会使用简单的UML(统一建模语言,Unified Modelling Languge)。由于市场上有很多介绍UML 的书,而作者在后面使用到的UML又极为简单,因此只在此作一极为简单的介绍,目的是让没有接触过UML的 读者能看懂后面的讲述。
图1. UML的类图举例 |
在图1的类图中可以看出,表示类的框分成四层:类名,变量清单,函数清单和属性清单。 变量名如是正体字,表明类是实的(Concrete,即可以实例化的类),变量名如是斜体字,表明类是抽象的。 显然,我们在图中给出了一个实的类。
在图1的类ClassUML中,一个变量或函数(方法)左面如果有一个加(+)号,表示它是公开的, 左面如果有一个减(-)号,表示它是私有的,左面如果有一个井(#)号,表示它是保护的。
一个属性即由一个内部变量,一个赋值函数(mutator)和一个取值函数(accessor)组成的结构。
在类的方框的右上角里,通常还分两行写出类的父类和所实现的接口。在后面读者会看到例子。
在类与类之间,会有线条指明它们之间的关系。在类与类之间可以发生推广(与继承相反),依赖,累积和关联 等关系。在后面读者看到例子时作者会加以解释。
- package com.javapatterns.singleton.demos;
- public class ClassUML {
- public ClassUML() {}
- private void aPrivateFunction() {}
- public void aPublicMethod() {}
- public int getAProperty(){ return aPrivateVar; }
- public void setAProperty(int aPrivateVar)
- { this.aPrivateVar = aPrivateVar; }
- static public void aStaticMethod() {}
- protected void aProtectedMethod() {}
- private int aPrivateVar;
- public int aPublicVar;
- protected int aProtectedVar;
- }
什么是创立性模式
单态模式的几种实现
图中的关系线表明,此类自已将自己实例化。 java 代码
代码清单2.饿汉式单态类。
懒汉式单态类 java 代码
图中的关系线表明,此类自已将自己实例化。 读者可能会注意到,在上面给出 懒汉式单态类实现里,使用了在多线程编程中常要使用的,著名的双重检查原则。对双重检查原则 和多线程编程要点不十分熟悉的读者,可以看看后面给出的问答题。 同样,由于构造子是私有的,因此此类不能被继承。 饿汉式单态类在自己被加载时就将自己实例化。既便加载器是静态的,在饿汉式单态类被加载时仍 会将自己实例化。单从资源利用效率角度来讲,这是比懒汉式单态类稍差些。从速度和反应时间角度来 讲,则比懒汉式单态类稍好些。然而,懒汉式单态类在实例化时必须处理好在多个线程同时首次引 用此类时,实例化函数内部关键段的访问限制问题。特别是当单态类作为资源控器,在实例化时必然涉及 资源初始化,而资源初始化很有可能耗费时间。这意味着出现多线程同时首次引 用此类的几率变得较大。 饿汉式单态类可以在爪哇语言内实现,但不易在C++内实现,因为静态初始化在C++里没有固定的顺序, 因而静态的m_instance变量的初始化与类的加载顺序没有保证,可能会出问题。这就是为什么GoF在提出 单态类的概念时,举的例子是懒汉式的。他们的书影响之大,以致爪哇语言中单态类的例子也大多是 懒汉式的。实际上,作者认为饿汉式单态类更符合爪哇语言本身的特点 |
登记式单态类
登记式单态类是GoF为了克服饿汉式单态类及懒汉式式单态类均不可继承的缺点而设计的。 作者把他们的例子翻译为爪哇语言,并将它自己实例化的方式从懒汉式改为饿汉式。只是它的 子类实例化的方式只能是懒汉式的,这是无法改变的。
图4. 登记式单态类的一个例子 |
图中的关系线表明,此类自已将自己实例化。
- package com.javapatterns.singleton.demos;
- import java.util.HashMap;
- public class RegSingleton {
- protected RegSingleton() {}
- static public RegSingleton getInstance(String name)
- {
- if (name == null)
- {
- name = "com.javapatterns.singleton.demos.RegSingleton";
- }
- if (m_registry.get(name) == null)
- {
- try
- {
- m_registry.put( name, Class.forName(name).newInstance() ) ;
- }
- catch(Exception e)
- {
- System.out.println("Error happened.");
- }
- }
- return (RegSingleton) (m_registry.get(name) );
- }
- static private HashMap m_registry = new HashMap();
- static
- {
- RegSingleton x = new RegSingleton();
- m_registry.put( x.getClass().getName() , x);
- }
- public String about()
- {
- return "Hello, I am RegSingleton.";
- }
- }
代码清单4. 登记式单态类。(注意为简单起见,这里没有考虑多线程访问限制的问题,读者可自行加入一个有双重 检查的访问限制)
它的子类
图5. 登记式单态类子类的一个例子。 图中的关系线表明,此类是由父类将自己实例化的。 |
- package com.javapatterns.singleton.demos;
- import java.util.HashMap;
- public class RegSingletonChild extends RegSingleton
- {
- public RegSingletonChild() {}
- static public RegSingletonChild getInstance()
- {
- return (RegSingletonChild) RegSingleton.getInstance(
- "com.javapatterns.singleton.demos.RegSingletonChild" );
- }
- public String about()
- {
- return "Hello, I am RegSingletonChild.";
- }
- }
代码清单5. 登记式单态类的子类。
在GoF原始的例子中,并没有getInstance()方法,这样得到子类必须调用文类的getInstance(String name) 方法,并传入子类的名字,很不方便。 作者在登记式单态类子类的例子里,加入了getInstance()方法,这样做的好处是RegSingletonChild 可以通过这个方法,返还自已的实例,而这样做的缺点是,由于数据类型不同,无法在RegSingleton提供 这样一个方法。
由于子类必须充许父类以构造子调用产生实例,因此它的构造子必须是公开的。这样一来,就等于允许了 以这样方式产生实例而不在父类的登记中。这是登记式单态类的一个缺点。
GoF曾指出,由于父类的实例必须存在才可能有子类的实例,这在有些情况下是一个浪费。 这是登记式单态类的另一个缺点.
爪哇语言里的垃圾回收
爪哇语言里垃圾回收使得单态类的使用变得有点复杂。原因就在于JDK1.1版里加进去的类的自动清除。 这种类的垃圾回收会清除掉类本身,而不仅仅是对象!事实上JDK1.1甚至可以清除掉一些系统类!
在JDK1.0.x版本里,类的自动清除尚未加入。
在JDK1.2及以后的版本里,升阳公司又收紧了类的垃圾回收规则,它规定,所有通过局部的和系统的 类加载器加载的类,永不被回收。并且,通过其它类加载器加载的类,只有在加载器自己被回收后才可被回收。
在1.1版JDK里使用单态类的读者,如果不了解这一版爪哇语言的特点,很有可能会遇到类消失掉的奇特问题。 为了使你的单态类能在所有版本的爪哇环境里使用,作者特别提供一个"看守"类程序,它能保证你的单态类, 甚至其它任何对象,一旦交给"看守"对象,即不会莫名其妙地被垃圾回收器回收,直到你把它从"看守" 那里把它释放出来。
图6. "看守"类的一个例子 |
- package com.javapatterns.singleton.demos;
- import java.util.Vector;
- /**
- * This class keeps your objects from garbage collected
- */
- public class ObjectKeeper extends Thread {
- private ObjectKeeper()
- {
- new Thread(this).start();
- }
- public void run()
- {
- try { join(); }
- catch (InterruptedException e) {}
- }
- /**
- * Any object passed here will be kept until you call discardObject()
- */
- public static void keepObject(Object myObject)
- {
- System.out.println(" Total number of kept objects: " +
- m_keptObjects.size());
- m_keptObjects.add(myObject);
- System.out.println(" Total number of kept objects: " +
- m_keptObjects.size());
- }
- /**
- * This method will remove the protect of the object you pass in and make it
- * available for Garbage Collector to collect.
- */
- public static void discardObject(Object myObject)
- {
- System.out.println(" Total number of kept objects: " +
- m_keptObjects.size());
- m_keptObjects.remove(myObject);
- System.out.println(" Total number of kept objects: " +
- m_keptObjects.size());
- }
- private static ObjectKeeper m_keeper = new ObjectKeeper();
- private static Vector m_keptObjects = new Vector();
- }
代码清单6. 看守类的一个实现。
看守类应当自我实例化,而且在每个系统里只需一个实例。这就意味着看守类本身就应当是单态类。当然,类 消失的事情绝不可以发生在它自己身上。作者提供的例子刚好满足所有的要求.
一个实用的例子
这里作者给出一个读取属性(properties)文件的单态类,作为单态类的一个实用的例子。 属性文件如同老式的视窗编程时的.ini文件,属于系统的“资源“,而读取属性文件即为资源管理, 显然应当由一个单态类负责。
图7. 这个例子的UML |
显然,在大多数的系统中都会涉及属性文件的读取问题,因而这个例子非常有实用价值。 在这个例子里,作者假定需要读取的属性文件就在当前目录中,且名为singleton.properties。 在这个文件中有如下的一些属性项:
- node1.item1=How
- node1.item2=are
- node2.item1=you
- node2.item2=doing
- node3.item1=?
代码清单7. 属性文件内容
本例子的源代码如下:
- package com.javapatterns.singleton.demos;
- import java.util.Properties;
- import java.io.FileInputStream;
- import java.io.File;
- public class ConfigManager
- {
- /**
- * 私有的构造子, 用以保证实例化的唯一性
- */
- private ConfigManager()
- {
- m_file = new File(PFILE);
- m_lastModifiedTime = m_file.lastModified();
- if(m_lastModifiedTime == 0)
- {
- System.err.println(PFILE + " file does not exist!");
- }
- m_props = new Properties();
- try
- {
- m_props.load(new FileInputStream(PFILE));
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
- /**
- *
- * @return 返还ConfigManager类的单一实例
- */
- synchronized public static ConfigManager getInstance()
- {
- return m_instance;
- }
- /**
- * 读取一特定的属性项
- *
- * @param name 属性项的项名
- * @param defaultVal 属性项的缺省值
- * @return 属性项的值(如此项存在), 缺省值(如此项不存在)
- */
- final public Object getConfigItem(String name, Object defaultVal)
- {
- long newTime = m_file.lastModified();
- // 检查属性文件是否被其它程序(多数情况是程序员手动)修改过。
- // 如果是,重新读取此文件。
- if(newTime == 0)
- {
- // 属性文件不存在
- if(m_lastModifiedTime == 0)
- {
- System.err.println(PFILE + " file does not exist!");
- }
- else
- {
- System.err.println(PFILE + " file was deleted!!");
- }
- return defaultVal;
- }
- else if(newTime > m_lastModifiedTime)
- {
- m_props.clear(); // Get rid of the old properties
- try
- {
- m_props.load(new FileInputStream(PFILE));
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
- m_lastModifiedTime = newTime;
- Object val = m_props.getProperty(name);
- if( val == null )
- {
- return defaultVal;
- }
- else
- {
- return val;
- }
- }
- /**
- * 属性文件全名
- */
- private static final String PFILE = System.getProperty("user.dir")
- + "/Singleton.properties";
- /**
- * 对应于属性文件的文件对象变量
- */
- private File m_file = null;
- /**
- * 属性文件的最后修改日期
- */
- private long m_lastModifiedTime = 0;
- /**
- * 属性文件所对应的属性对象变量
- */
- private Properties m_props = null;
- /**
- * 本类可能存在的唯一的一个实例
- */
- private static ConfigManager m_instance = new ConfigManager();
- }
代码清单8. ConfigMan的源代码。
显然,作者是用饿汉型实现方法,从而避免了处理多线程访问可能引起的麻烦。在下面的源代码里,作者演示了怎样利用看守类来"看守"和"释放"ConfigMan类,以及怎样调用ConfigMan来读取属性文件。
- ObjectKeeper.keepObject(ConfigManager.getInstance());
- BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- System.out.println("Type quit to quit");
- do
- {
- System.out.print("Property item to read: ");
- String line = reader.readLine();
- if(line.equals("quit"))
- {
- break;
- }
- System.out.println(ConfigManager.getInstance().getConfigItem(line,
- "Not found."));
- } while(true);
- ObjectKeeper.discardObject(ConfigManager.getInstance());
代码清单8. ConfigMan的源代码。
显然,作者是用饿汉型实现方法,从而避免了处理多线程访问可能引起的麻烦。 在下面的源代码里,作者演示了怎样利用看守类来"看守"和"释放"ConfigMan类,以及 怎样调用ConfigMan来读取属性文件。
- ObjectKeeper.keepObject(ConfigManager.getInstance());
- BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- System.out.println("Type quit to quit");
- do
- {
- System.out.print("Property item to read: ");
- String line = reader.readLine();
- if(line.equals("quit"))
- {
- break;
- }
- System.out.println(ConfigManager.getInstance().getConfigItem
- (line, "Not found."));
- } while(true);
- ObjectKeeper.discardObject(ConfigManager.getInstance());
代码清单9. 怎样调用ConfigMan类以读取属性文件,及调用看守类来看守和释放ConfigMan类
下面的图显示出上面代码运行时的情况。
问答题 java 代码
java 代码
代码清单11. 几种单态类的使用方法。 from: http://blog.csdn.net/lizl/archive/2005/07/26/435215.aspx |
相关推荐
章节介绍:1、爪哇语言结构性模式之变压器模式介绍 2、爪哇语言抽象工厂创立性模式介绍 3、工厂方法创立性模式介绍 4、单态创立性模式介绍 5、单态创立性模式介绍 6、观察者模式介绍7、责任链模式 8、设计模式之...
在Java、C#等面向对象编程语言中,单态模式的实现通常分为几种方式: 1. 饿汉式(Eager Initialization):在类加载时就完成实例化,这种方式保证了单例的唯一性,同时也确保了线程安全。但是可能会造成内存浪费,...
单态模式的定义: Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 在项目的很多地方都会用到它,比如说数据库的链接。 使用Singleton的好处还在于可以节省内存,因为它限制了实例...
### Java中单态设计模式详解 #### 一、引言 设计模式是在长期软件开发过程中提炼出来的最佳实践,它们提供了一种标准化的方式用于解决特定类型的问题。对于Java开发者而言,熟悉并掌握各种设计模式是非常重要的,...
在实际应用中,单态模式常用于配置管理、日志记录、数据库连接池等场景,这些场景需要确保在整个应用中只有一个共享的对象,以保证数据的一致性和性能。但需要注意的是,过度使用单态模式可能会导致设计过于僵化,...
升级标签可能是指在项目升级过程中,如何利用单态模式保持数据一致性或简化升级流程。例如,一个数据库连接管理的单例类可以在升级前后保持相同的连接配置,简化数据迁移过程。 综上所述,Net单态模式的案例涵盖了...
总结来说,单态模式关注的是保证类的唯一性,适用于需要全局唯一实例的场景;而简单工厂模式则关注于对象的创建过程,将创建逻辑封装起来,让客户端更加关注于业务逻辑,而非对象的创建。两者在软件设计中都有其独特...
理解并熟练应用单态模式和简单工厂模式,能够帮助开发者更好地设计和组织代码,提高软件的可维护性和可扩展性。在学习和实践中,不仅要注意模式的实现,还要考虑其在不同场景下的适用性以及可能带来的问题,如单例...
单态模式是在面向对象设计中实现类似单例行为的一种替代方法,确保Java应用程序中的共享状态。它强制实现一种独特的行为,即类的所有实例共享相同的状态。与单例模式不同,单例模式将类限制为单个实例,单态模式允许...
在.NET中,C#语言提供了多种实现单态模式的方式: 1. **经典实现**:使用`private`构造函数和`public static`的实例获取方法。这是最常见的实现方式,例如: ```csharp public class Singleton { private static ...
单态模式(Singleton Pattern)是设计模式中的一种,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。在MFC(Microsoft Foundation Classes)框架中,单态模式的应用同样重要,尤其对于需要全局共享的...
在Java或其他面向对象语言中,单态模式的实现有多种方式,但核心思想都是限制类的实例化过程。 一、单态模式的基本结构 单态模式通常包含以下关键部分: 1. 单例类:这个类只能被实例化一次,它负责创建自己的唯一...
单态模式和简单工厂模式.doc
综上所述,Java实现的单态登录涉及单态模式、会话管理、跨域共享、过滤器、分布式环境下的同步以及安全性考虑等多个方面。实际开发时,应根据项目需求选择合适的方法和工具进行实现。提供的压缩包文件...
单态模式(Singleton Pattern)是一种常用的软件设计模式,它的核心目标是确保一个类在整个应用程序中只有一个实例,并提供全局...在某些情况下,如依赖注入框架或使用枚举类型替代,可以避免单态模式带来的复杂性。
单态模式(Singleton Pattern)是设计模式中的一种基础模式,主要用来确保一个类只有一个实例,并提供一个全局访问点。在软件工程中,当一个类只能有一个实例而且客户可以从一个众所周知的访问点访问它时,这样的...
Java设计模式是软件开发中的重要概念,它们是解决常见...这个压缩包资料“[浪曦原创]JAVA设计模式 第2讲 单态模式和简单工厂模式(jzkangta)”应包含了详细的讲解和示例代码,可以帮助深入理解和应用这两种设计模式。
有利于学习和掌握单态模式,是我们学习的关键
单态模式(Singleton模式)是Java设计模式中的一种,它的主要目标是确保一个类在整个应用程序中只有一个实例存在。这种模式的应用场景广泛,特别是在需要全局共享的资源管理、配置中心、日志服务等场合非常常见。 ...
单态(Singleton)模式是软件设计模式中的一种,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。...理解和熟练掌握单态模式的实现方式和应用场景,对于提升代码质量和维护性至关重要。