说到设计模式,很多人都听过什么23中设计模式,或者一些常见的模式名称,在Java中确实有23种设计模式,但是设计模式并不是随着Java的开发而产生的,它是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结,是由无数的开发者总结出来的一些代码经验,针对一些比较特殊的场合。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样;
现在我们介绍其中的两种设计模式单例模式和代理模式
单例模式:该类的对象只能创建一个
以前在写代码时,我们可以在外面想创建几个对象就创建几个对象,但凡外界使用new 就可以创建新的对象,现在我们要杜绝外界使用new,不让外界创建对象则私有化构造函数:
class Demo{
private Demo(){}
}
现在外界不能创建对象,那么外界想要获得该类的对象调用该类的方法如何解决呢?——在内部创建该类的对象,因为内部可以调用构造函数,之前我们在介绍成员和静态的特点中可知,定义在类中的本类对象要用static进行修饰,那么就将创建的对象当做静态的成员变量,且对外还是不可访问的,即:
class Demo{
private static Demo d=new Demo();
private Demo(){}
}//在该类外用完进行释放
Demo.d=null;
现在又有一个新问题,既然对象被静态同时也被私有了,那么外界要如何访问该对象呢?——提供一个函数对外开放,函数里面返回该类创建的对象,然后在外用类名调用该函数得到对象
class Demo{
private static Demo d=new Demo();//0x123
private Demo(){}
public static Demo getInstance(){
return d;
}
}
Demo d1=Demo.getInstance();
Demo d2=Demo.getInstance();
d1=null;
单利模式分为两种形式,即饿汉模式和饱汉模式。
饿汉模式
是直接先创建一个该类的对象,提供一个访问的方法将该类创建的对象返回出来;
//单例模式-饿汉式
class Singleton{
private static Singleton s=new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return s;
}
}
饱汉模式
则是,先定义一个该类的引用变量,在提供访问的方法中先判断该类引用所指向的对象是否存在,如果存在,则直接将该对象返回,不存在才创建该类的对象。
//单例模式-饱汉式
class Singleton{
private static Singleton s=null;
private Singleton(){}
public static Singleton getInstance(){
if(s==null){
s=new Singleton();
}
return s;
}
}
单例模式的好处:减少重复创建对象,从而节约内存
代理模式
代理模式其实就是一个代理人和委托人之间的关系一样,就好比明星与他的助理之间的关系,比如某明星要开一场演唱会,具体的唱跳是由他自己实现,而舞台的搭建和时间则是通过他的助理做好这一切,其中这个助理就是代理人,我们来看一下代码的体现:
class Demo09{
public static void main(String[] args){
ZhuLi zl=new ZhuLi ("张靓颖"); //这里找到一个助理,传进一个名字,相应的就是谁的助理
zl.sing(); //调用方法
zl.dance();
}
}
interface Singer{ //定义一个歌手的接口
public void sing(); //每个歌手都会唱歌
public void dance(); //每个歌手可能会一点舞蹈
}
class ZhuLi implements Singer{ //定义一个助理类也实现了歌手的方法,这是一个代理人
Singer s; //定义一个接口的引用
ZhuLi (String name){ //创建助理对象时将相应的歌手名字传进来就相当于找到了他相应的助理人
if(name.equals("王力宏")){
s=new WangLiHong(); //如果是王力宏,就创建一个王力宏的对象
}
if(name.equals("张靓颖")){ //如果是张靓颖,就创建一个张靓颖的对象
s=new ZhangLiangYin();
}
}
public void sing(){ //助理当中也会实现唱歌的方法,不过他只是一个通知者,通知舞台和时间已经准备好,让相应的对象去完成相应的任务
s.sing(); //这里通知该对象去做唱歌这个任务
}
public void dance(){ //与上面同理
s.dance();
}
}
class WangLiHong implements Singer{ //定义一个WangLiHong类实现歌手的方法,这是一个委托人
public void sing(){ //这里委托人会完成自己相应的任务
System.out.println("王力宏正在舞台上给大家唱《大城小爱》");
}
public void dance(){
System.out.println("王力宏给大家来了一段舞蹈");
}
}
class ZhangLiangYin implements Singer{ /定义一个ZhangLiangYin类实现歌手的方法,这也是一个委托人
public void sing(){
System.out.println("张靓颖刚刚唱了一首《画心》");
}
public void dance(){
System.out.println("张靓颖跳了一段名族舞");
}
}
所以使用代理模式要明确三点:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用
代理模式的优点:
(1).职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
(3).高扩展性