java学习笔记之
设计模式(一)——单例设计模式
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
设计模式分为三种类型,共23种:
-
创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
-
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
-
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。
单例模式
意图:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用性:
-
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
-
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时
保证对象的唯一:
1.为了避免其他程序过多建立该类对象,先禁止其他程序建立该对象。
2.为了让其他程序可以访问到该对象,只好在本类中,自定义一个对象
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式
这3步的代码为:
1.将构造函数私有化
2.在类中创建一个本类对象
3.提供一个方法可以获取到该对象
如下:
class Single
{
<span style="color:#ff0000;">private Single(){}
private static Single s = new Single();
public static Single getInstance()
{
return s;
}</span>
}
public class SingleDemo {
public static void main(String[] args) {
Single ss = Single.getInstance();
}
}
方法被调用只用两种方式:通过对象或者类名。
例子中,无法创建对象,因此不能通过对象调用方法,因此要用类名调用,所有该方法必须是静态方法,
静态方法需要访问类的成员,成员被访问,也要静态。
下面测试一下:
class Single
{
private int num;
public void setNum(int num)
{
this.num=num;
}
public int getNum()
{
return num;
}
private Single(){}
private static Single s = new Single();
public static Single getInstance()
{
return s;
}
}
public class SingleDemo {
public static void main(String[] args) {
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
s1.setNum(23);
System.out.println(s2.getNum());
}
}
输出结果:23
可见例子中,s1,s2,s引用同一个对象,不能在另外创建对象
对于事物该怎么描述还怎么描述,当需要该事物的对象保证在内存中唯一时,就将上面的3步加上即可。
上述方法是先初始化对象,因此叫 饿汉式
还有一种方法,在方法被调用时才初始化对象,也叫做对象的延迟加载,称为懒汉式
代码如下:
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}
懒汉式中,Single类进内存,对象还没有存在,只有调用getInstance方法时,才建立对象。
开发软件一般使用饿汉式!
因为懒汉式不安全!必须加同步!
class Single
{
private static Single s = null;
private Single(){}
public static synchronized Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}
这种同步代码块消除了安全问题,但是效率降低了,因为有程序试图调用方法时都要判断锁。
为此我们运用双重否定提高代码效率:
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
s = new Single();
}
}
return s;
}
}
这样如果对象已经创建,那么以后有程序再试图创建对象时,判断语句失败,就不用判断锁了,提高了效率。