Activity之常见布局初步

前一篇博客记录了在activity中有哪些控件可供我们使用,既然牵涉到控件,那么肯定会牵涉到控件的布局,也就是在activity中怎么摆放这些东西,我们先看看activity的布局方式有哪些:LinearLayout线性布局、TableLayout表格布局、RelativeLayout相对布局、AbsoluteLayout绝对布局、FrameLayout帧布局等五种,各有各的用途和用法,其中老夫认为最常用的是前三种,最最常用的应该就是前两种了,今天我们就介绍一下前三种的用法。 首先看第一个也是非常常见的也是非常简单的LinearLayout线性布局方式,布局文件为: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- android:id 为控件指定相应的ID android:text 指定控件中显示的文字,需要注意的是:这里最好使用strings.xml android:gravity 指定控件中内容的基本位置,比如居中、靠左等 android:textSize 指定控件中字体的大小 android:background 指定控件的背景色,使用RGB命名法 android:width 指定控件的宽度 android:height 指定控件的高度 android:layout_width 和父控件的关系,例如是匹配内容还是在水平方向上填满父控件 android:layout_height 和父控件的关系,例如是匹配内容还是在垂直方向上填满父控件 android:padding* 指定控件的内边距,也就是说控件中内容 android:singleLine= 布尔值,如果为真,则控件中的内容将在一行中显示 --> <TextView android:id="@+id/firstTextView" android:text="第一行" android:gravity="center_vertical" android:textSize="20pt" android:background="#ff0000" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="10dip" android:paddingTop="20dip" android:paddingRight="30dip" android:paddingBottom="40dip" android:singleLine="false" /> <TextView android:id="@+id/secondTextView" android:text="第二行" android:gravity="center_vertical" android:textSize="30pt" android:background="#00ff00" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 其中LinearLayout表示采用线性布局方式,第五行:android:orientation=“vertical"表示是在水平方向还是在垂直方向上线性布局,注释中为该元素设置样式的各种含义。 需要说明的是,LinearLayout是可以嵌套的,下面给出一个例子: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_weight="1" > <TextView android:id="@+id/firstTextView" android:text="第一行" android:gravity="center_vertical" android:textSize="20pt" android:background="#ff0000" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="10dip" android:paddingTop="20dip" android:paddingRight="30dip" android:paddingBottom="40dip" android:singleLine="false" /> <TextView android:id="@+id/secondTextView" android:text="第二行" android:gravity="center_vertical" android:textSize="30pt" android:background="#00ff00" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_weight="1" > <TextView android:id="@+id/firstTextView" android:text="第一行" android:gravity="center_vertical" android:textSize="20pt" android:background="#ff0000" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="10dip" android:paddingTop="20dip" android:paddingRight="30dip" android:paddingBottom="40dip" android:singleLine="false" /> <TextView android:id="@+id/secondTextView" android:text="第二行" android:gravity="center_vertical" android:textSize="30pt" android:background="#00ff00" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> 关于嵌套需要说明的是,1. 最外层的android:orientation=“vertical"表示内部所有的LinearLayout的布局方式,当然每一个LinearLayout的android:orientation=“vertical"表明自己内部每一个元素的布局方式;2. 每一个LinearLayout的android:layout_weight=“1"表示该LinearLayout的权重,即该LinearLayout在所有空间中所占的比例。最后需要说明的是,这个我是把第一个文件直接拷过去的,所以ID有重复,大家记得改一下 下面我们看第二种布局方式:TableLayout表格布局,其中我个人感觉这种布局方式用的应该不是很多,下面我们看看其布局文件: ...

January 18, 2015 · 2 分钟 · Bridge Li

Android之常见控件

在我们开发Android的时候,有各种各样常见的控件供我们使用,今天就记录一下这些常见的控件有哪些,其实他们的用法大多一样,希望能举一反三, 第一个常见的控件恐怕就是EditText、TextView、Button,使用的例子如下: activity_main.xml布局文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/factorOne" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <TextView android:id="@+id/symbol" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <EditText android:id="@+id/factorTwo" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <Button android:id="@+id/calc" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> 对应的activity: package cn.bridgeli.demo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity { private EditText factorOne = null; private TextView symbol = null; private EditText factorTwo = null; private Button calc = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); factorOne = (EditText) findViewById(R.id.factorOne); symbol = (TextView) findViewById(R.id.symbol); factorTwo = (EditText) findViewById(R.id.factorTwo); calc = (Button) findViewById(R.id.calc); symbol.setText(R.string.symbol); calc.setText(R.string.calc); calc.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { String firstNum = factorOne.getText().toString(); String secondNum = factorTwo.getText().toString(); Intent intent = new Intent(); intent.setClass(MainActivity.this, ResultActivity.class); intent.putExtra("firstNum", firstNum); intent.putExtra("secondNum", secondNum); startActivity(intent); } }); } } result.xml布局文件就比较简单了,只有一个TextView ...

January 11, 2015 · 4 分钟 · Bridge Li

Activity之生命周期

这几天没事,自学了一下Android的开发,今天记录一下activity的生命周期,在写之前,我们先看一下,Google官方的文档,窃以为这个说的已经比较清楚明白了: 从这张图,我们清楚无误的看到,activity的生命周期方法执行顺序为:onCreate()–>onStart()–>onResume()–>onPause()–>onStop()–>onRestart()–>ondestory() 但是口说无凭,我们从一个例子中说明问题: 第一个activity: package cn.bridgeli.lifecycle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button button = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); ButtonListener buttonListener = new ButtonListener(); button.setOnClickListener(buttonListener); System.out.println("First activity onCreate"); } class ButtonListener implements OnClickListener{ @Override public void onClick(View arg0) { Intent intent = new Intent(); intent.setClass(MainActivity.this, SecondActivity.class); startActivity(intent); } } @Override protected void onDestroy() { super.onDestroy(); System.out.println("First activity onDestroy"); } @Override protected void onPause() { System.out.println("First activity onPause"); super.onPause(); } @Override protected void onResume() { super.onResume(); System.out.println("First activity onResume"); } @Override protected void onStart() { super.onStart(); System.out.println("First activity onStart"); } @Override protected void onStop() { super.onStop(); System.out.println("First activity onStop"); } @Override protected void onRestart() { super.onRestart(); System.out.println("First activity onRestart"); } } 第二个activity: ...

January 4, 2015 · 2 分钟 · Bridge Li

软件属性小结

一. 功能属性 Use Story和Use Case 功能的三个要素 ①. 参与者 用户、角色、用户和角色的关系 ②. 流程 整体流程、页面操作流程 ③. 表单(UI) 正确性(精确性) 二. 决定与架构 权衡软件质量属性 架构元素 ①. 架构(决定)过程 ②. 架构(决定)产物 架构(架构元素集合) 三. 质量属性(非功能性属性) 开发期质量属性 ①. 易理解性和可读性 所有烦人工作成果(如需求文档、设计文档、code等)易读、易理解,可以提高团队开发性率,降低维护成本 考虑的因素:拒绝啰里啰嗦、复杂问题简单化、拒绝学术化、严格遵守codestyle(一旦定下来,团队所有成员必须无条件遵守!!!) ②. 可扩展性 可扩展性是软件适应变化的能力,在软件开发过程中变化时司空见惯的,如需求、设计、算法的改进,程序的变化的等等。 考虑的因素:增量开发、小型大型软件、是否有下一个版本 ③. 可重用性 重复利用软件的中某一个组件(如文档模板、架构框架、代码)的能力 考虑的因素:架构(框架)重用、模块重用、重用与分层 ④. 可测试性 软件测试的难易程度,软件的可测试性是指软件发生故障并隔离、定位其故障的能力特性,以及在一定的时间和成本的前提下,进行测试设计、测试执行的能力,例如Controller层不要和request、response等耦合、表单等要有Id(为了自动化测试)等 ⑤. 可维护性 可维护性是指理解、改正、改动、改进软件的难易程度,影响可维护性的因素有:可理解性、可测试性、可扩展性 改正性维护:软件在使用中发现了隐藏的错误后,为了诊断和改正这个隐藏错误而修改软件的活动 适应性维护:为了适应变化了的环境而修改软件的活动,如:数据库、操作系统、服务器网络带宽等 完善性维护:为了扩充或完善原有软件功能或性能而改动软件的活动 预防性维护:为了提高软件的可维护性和可靠性,为未来的进一步改进打下基础而修改的活动 ⑥. 可移植性 是指软件不经修改或稍加修改就可以运行于不同软硬件环境(CPU、OS)的能力,主要是代码的可移植性 考虑的因素:硬件之间、数据库之间 ⑦. 兼容性 不同软件或新老版本之间交换信息的能力 考虑的因素:版本之间的兼容、软件之间的兼容,例如:老的客户端能否调用新的服务器版本的API,office和wps兼容性问题(这个存在强势问题,例如微软比较强大、用户比较多,我们就可以不兼容你们金山) 运行期质量属性 ①. 性能 性能通常是指软件的“时间-空间”效率,而不是软件的运行速度。人们总希望软件的运行速度高些,并且占用资源少些,一言以蔽之:既要马儿跑得快,又要马儿吃得少,即性价比最高。 性能优化的关键是:找出限制性能的瓶颈,原则是:管理好自己,控制好别人,那么自己是谁?别人有是谁呢?自己一般是进程(拥有)、内存(分配给自己的)、程序;别人一般是:数据库、文件、其他系统、网络。 控制别人,对外资源(数据库连接、文件流、socket等)一定要关闭,而且在finally里面关闭,当然一些连接可以使用池的概念。 管理好自己,数据库调优、JVM调优、堆栈内存大小的设置等这是一个很大的概念,希望将来能有一篇专门的文章来写这个,其实关于这个网上的资料也挺多的,大家可以自己搜一些来自学一下 ②. 安全性 这里的安全性是指信息安全,英文原文是指:security而不是safety,安全性是指防止系统被非法入侵的能力,即属于技术问题又属于安全问题。那么什么样的系统是安全的呢?一般的,如果黑客为非法入侵花费的代价(时间、费用、风险等等)高于得到的好处,那么这样的系统可以认为是安全的 考虑的因素:同源策略、SQL输入、跨站脚本攻击、跨站请求伪造、加密解密技术、API安全性,这些每一个都是一门学问,大家可以自己都一些资料,自己去学习一下 ③. 易用性 用户(是指最终用户)使用软件的容易程度,最终用户并不关心软件是怎么实现的,他们只关心UI、操作的方便性、流程的简易程度 ④. 可用性 这个比较难描述,只要出现问题就是不可用的,例如:银行系统,A用户向B用户转账,A的钱扣了,B却没收到等等 ⑤. 可伸缩性 代表一种弹性,在系统扩展成长的过程中,软件能够保证旺盛的生命力,通过很少的改动甚至只是硬件设备的添置,就能实现整个系统处理能力的线性增长,实现高吞吐量和低延迟的高性能。 考虑的因素:数据库是否支持集群、web服务器的集群(session本地问题、文件本地化问题) ⑥. 互操作性 一般是指对外提供API的调用难易,例如一些开放平台 ⑦. 可靠性 在给定的条件下,在给定的时间内,系统不发生故障的概率,可靠性问题一出现一般是很难发现的,他出现无规律,时隐时现 ⑧. 健壮性 是指在异常情况下,软件能够正常工作的能力 异常:与预期产生不同结果都叫异常,预期:和用户的预期、QA的预期、需求文档的预期(主要是这个,即运行结果和需求文档描述不一致) 例如:用户注册输入一个已存在的用户名,怎么做?(应该提示用户,不能抱一个505错误)、数据库宕机、网络慢等情形下该怎么做? 容错能力:异常发生后,软件能否正常运行,例如:数据库主从备份、多服务器集群,用户输入错误的数据,能提示用户 恢复能力:例如数据备份,当一个数据库宕机之后,另一个备份数据库能自己立马启动,接下宕机服务器的任务继续工作

December 28, 2014 · 1 分钟 · Bridge Li

数据加密算法之MD5和SHA1

这个星期记录一下数据加密算法,记得刚开始学编程的时候就有一个疑问:我们的密码就这么放在数据库里面,多不安全啊,数据库管理员不是拿着数据想干嘛就干嘛吗?但是由于认知有限,一直没有解决这个问题,直到去年实习时,当时的项目经理Zack说,用户密码不能明文存放到数据,必须经过MD5加密,终于解决了这个问题。因为MD5的不可逆性,所以就算知道MD5码,只要你不是一些弱密码,一般情况下发生泄密的可能性是非常非常小的,几乎可以认为是绝对安全的,但MD5实现的实现却很简单,今天就记录一下实习时用到的一个MD5加密算法的一个实现: package cn.bridgeli.demo; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Encryption { public static String MD5(String input) { StringBuffer hexString = null; try { // 获得MD5摘要算法的 MessageDigest 对象 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的字节更新摘要 mdInst.update(input.getBytes()); // 获得密文 byte[] md = mdInst.digest(); // 把密文转换成十六进制的字符串形式 hexString = new StringBuffer(); // 字节数组转换为 十六进制数 for (int i = 0; i < md.length; i++) { String shaHex = Integer.toHexString(md[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return hexString.toString(); } public static String SHA1(String decript) { StringBuffer hexString = null; try { MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1"); digest.update(decript.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String hexString = new StringBuffer(); // 字节数组转换为 十六进制数 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return hexString.toString(); } } 这里面还有一个SHA1机密算法的实现,主要是在自学微信开发时,微信在接入验证的数据经过字典排序后SHA1加密,所以就顺便记录了一下,算是两个比较常用的加密算法吧,供大家参考。 ...

December 21, 2014 · 1 分钟 · Bridge Li

设计模式综合运用之Excel导入

学以致用,前几篇文章我们学了很多设计模式,今天我们就把这些模式综合运用一下,看看实际应用是怎么导入Excel的,(当然这里面没有用到侦听者模式) 我们先看一下Excel的样子: 因为是Excel的的解析,所以应该是前台上传的,我们应该有一个Servlet来接收前台传过来的数据: package cn.bridgeli.demo.servlet; import java.io.File; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.bridgeli.demo.servce.Container; import cn.bridgeli.demo.servce.ExcelParseStrategy; public class ExcelParseServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //真正的情况下应该由前台传过来的,这里是模拟就写死了 File file = new File("D:/Excel.xls"); String excelType = request.getParameter("excelType"); // 此处是策略模式,至于怎么实现,大家可以参考策略模式 Container container = new Container(); ExcelParseStrategy excelParseStrategy = container.getStrategy(excelType); excelParseStrategy.parse(file); } } 下面看ExcelParseStrategy接口,和具体策略的实现: ...

December 14, 2014 · 3 分钟 · Bridge Li

设计模式之模板方法

这一节记录一下模板方法,在学模板方法之前,要先学习一下什么是模板,模板其实就是一个例子,例如我们做市场调研时,调研人员会给我们一个表格,我们只需要回答一些答案即可,映射到我们的代码中就是这个样子: aaaaaaaa bbbbbbbb cccccccc ******** dddddddd eeeeeeee ######## ffffffff gggggggg $$$$$$$$ 这是我们第一次写的代码,但是我们在后来的coding中发现,这一段代码我们需要copy一份,只需要该其中的第四行、第七行、第十行就行了,其余的不需要做修改,如果我们copy过去,改一下这么做虽然可以完成,但我们想一想如果我们代码里面一万处这样的代码,难道要copy一万次?这么做是不是很冗余?这时候就需要我们的模板方法上场了,下面看一个我们在实际中的典型应用:JDBC操作数据库,所以我们下面先看一个操作数据库的实际例子: package cn.bridgeli.demo.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import cn.bridgeli.demo.entity.User; import cn.bridgeli.demo.util.DBUtil; public class UserDao { public User getUserById(int userId) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; User user = null; String sql = "SELECT * FROM user WHERE id = ?"; try { conn = DBUtil.getConn(); pstmt = DBUtil.getPstmt(conn, sql); pstmt.setInt(1, userId); rs = pstmt.executeQuery(); if (rs.next()) { user = new User(); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs); DBUtil.close(pstmt); DBUtil.close(conn); } return user; } } 这段代码经过我们分析,很明显就建行不一样:String SQL不一样,pStmt设置参数不一样,if(rs.next())不一样,所以我们可以把它做成模板方法,下面我们就重构着一段代码。在重构这段代码之前有几个问题我们先要明确: ...

December 7, 2014 · 2 分钟 · Bridge Li

设计模式之策略模式

今天我们来讨论策略模式,策略模式是一个比较难理解的模式,尤其是和工厂模式相结合时,当时看程杰的《大化设计模式》时,第二个讲的就是这个,那是一个迷迷糊糊啊,其实仔细分析策略模式并没有那么难,在我们学策略模式之前,先搞明白什么是策略呢?策略是:在某一件事上,在一定的情况下,所采取的行动。当然这个“在一定的情况下”一定是某一种情况,也即是可数的。当情况很多的时候,也许我们要用很多烦人if-else去处理,所以策略模式就是解决这类问题的,其一个典型应用就是在电商平台中:不同的用户有不同的等级享有不同的折扣,我想有些人第一想到的处理方式就是: package cn.bridgeli.demo; public class Strategy { public double discount(String grade, double total) { if ("A".equals(grade)) { return total * 0.6; } else if ("B".equals(grade)) { return total * 0.7; } else if ("C".equals(grade)) { return total * 0.8; } else if ("D".equals(grade)) { return total * 0.9; } else { return total; } } } 我相信这么处理只要看过上篇文章的人都会想到,不满足:开闭原则!当我们新增一个策略时,肯定要该这段代码,增加一个if,当我们的策略发生变化时,例如不仅打折而且在过节时发送促销邮件之类的,那么里面的策略也要改,显然这是一个大问题,那么出现这个问题的根源就是不满足:迪米特原则。 ps:就算不用if-else,用switch-case也有同样的问题。那么用策略模式怎么处理呢? 需要我们首先定义一个策略模式的接口: package cn.bridgeli.demo.service; public interface UserGradeStrategyService { public double discount(); } 下面是具体的策略的实现 package cn.bridgeli.demo.service; public class UserGradeAStrategyService implements UserGradeStrategyService { @Override public double discount() { return 0.6; } } package cn.bridgeli.demo.service; public class UserGradeBStrategyService implements UserGradeStrategyService { @Override public double discount() { return 0.7; } } package cn.bridgeli.demo.service; public class UserGradeCStrategyService implements UserGradeStrategyService { @Override public double discount() { return 0.8; } } package cn.bridgeli.demo.service; public class UserGradeDStrategyService implements UserGradeStrategyService { @Override public double discount() { return 0.9; } } package cn.bridgeli.demo.service; public class UserGradeEStrategyService implements UserGradeStrategyService { @Override public double discount() { return 1.0; } } 有一个策略的容器,这个容器知道都有哪些策略,它里面包含所有的策略: ...

November 30, 2014 · 2 分钟 · Bridge Li

设计模式之侦听者模式

关于技术,老夫一直认为应该以实用为主,至于那些理论性的东西,用得多了慢慢就理解了,所以为了说明今天这个设计模式,我们先提出一个问题:我们知道很多系统都有注册功能,有些呢,直接返回您已注册成功请直接登录,而有些注册则要求相对比较比较高,例如注册成功之后需要向用户填写的手机发送短信、Email发送邮件之类的,关于这个问题,大家立马想到的也许是这么来实现吧: package cn.bridgeli.regdemo.service; public class UserService { public void register(String username, String password) { // 非空验证 // save到数据库 // 发送短信说,注册成功 // 发送邮件说,注册成功 } } 这是一个很中规中矩的写法,我们都知道面向对象有一个原则是:单一职责原则,也即是最小知识化原则,好像也称迪米特原则和不和陌生人说话,不管怎么说,就是一个类只管一个类型的东西,一个方法只干一件事,例如本例中的注册,那么应该只干注册一件事,至于什么发短信啊,发邮件啊,本质上来说和注册是没有关系的,所以我们可以把发短信,发邮件的方法提取出来,放到其他的地方,例如放到工具类里面,那么提取出来是不是就是最好的了呢?我们应该知道面向对象还有一个原则:开闭原则,这个原则是说,对扩展开放对修改关闭,也就是说,当我们需求发生变化的时候,不应该依赖于去修改源码,而是依赖于对源码的扩展,所以关于我们这个例子:假设有一天我们不需要发送短信了,或者需要有第三种通知用户的方式,您是否能做到不修改源码呢?肯定做不到吧,只有把调用发送短信的代码删了,或者在下面添加第三种通知方式,所以这么做肯定还是不够的,那么为了满足:开闭原则,我们就要引入今天的设计模式:侦听者模式,且看下面的例子: package cn.bridgeli.regdemo.service; import cn.bridgeli.regdemo.listener.EventLinstener; public class UserService { public void register(String username, String password) { // 非空验证 // save到数据库 EventLinstener eventLinstener = new EventLinstener(); String data = "注册成功"; eventLinstener.dispatchEvent("REGSUCESSED", data); } } 核心类EventLinstener package cn.bridgeli.regdemo.listener; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class EventLinstener { public static Map<String, List<Observer>> events = new HashMap<String, List<Observer>>(); static { List<Observer> reg = new ArrayList<Observer>(); reg.add(new EmailObserver()); reg.add(new SmsObserver()); events.put("REGSUCESSED", reg); } public void dispatchEvent(String eventName, Object object) { List<Observer> observers = events.get(eventName); if (null != object && !observers.isEmpty()) { for (Observer observer : observers) { observer.execute(object); } } } } 侦听者抽象类Observer ...

November 23, 2014 · 1 分钟 · Bridge Li

设计模式之单例模式

在程序设计中,单例模式是非常常用的一个设计模式,至于有点老夫就不用多说了,肯定有一点比较省内存,但什么的类适合于设置成单例呢?一言以蔽之: 在程序设计中,无状态的类都可以设置成单例。 那么问题来了,什么样的类是无状态的,什么样的类是有状态的呢?其实很简单: 没有数据,也就是说这个类只有方法,没有成员变量。 举个例子: User类是否可以设置成单例呢?肯定不行,因为User类每一个对应的Id肯定是不同的人,如果设置成单例,数据就乱了;但一般Service层、DAO层的方法呢?这个一般都是一些业务逻辑,只有一些方法,没有数据,所以肯定可以设置成单例,事实上我们这些类如果有Spring托管,那么自然而然这些类就是单例的。 既然单例使用这么多,有点还这么明显,那么怎么设置一个类是单例的呢?根据老夫第一个项目经理Zack的说法,设置一个类成单例的,有两种方法,首先看第一个,传统意义上的单例: package cn.bridgeli.singleton; public class Singleton { private static volatile Singleton singleton = null; private Singleton() { } public static Singleton getInstance() { if (null == singleton) { synchronized (Singleton.class) { if(null == singleton) { singleton = new Singleton(); } } } return singleton; } } 这个最简单,构造方法设置成私有的,别人就不能new了,想获取实例必须通过getInstance()方法,而这个方法里面是static的,所以这是一个传统意义上的最简单的单例。 除此之外,我们还可以借助于静态内部类的方式实现单利: package cn.bridgeli.demo.singleton; public class Singleton { private Singleton() { } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } } 第二个,管理意义上的单例 我们自己观察可以发现,这个虽然简单,但我们Spring实现的单例,肯定不是这么实现的,那么他是怎么实现的呢?Spring并没有限制我们自己写的类必须要有一个私有的构造方法,所以管理意义上的单例,并不要一个类有一个私有的构造方法,但他会通过一个BeanFactory产生我们想要的实例,参考代码如下: ...

November 16, 2014 · 1 分钟 · Bridge Li