今天整理了一下已学的几种JAVA设计模式,也是比较经典常用的几种。
1 单例模式singelton 项目开发中往往有这样的需求:某个对象 只需要存在一个(不用new出多个) 即保证该类有且只有一个实例
单例模式有两种实现方法
(1)饿汉式(下面通过一段代码进行解析)
class Singlet{ //构造方法私有化 不允许外界再创建 private Singlet(){ } //static Singlet s = new Singlet(); private static Singlet s = new Singlet(); //加了private 外界又无法访问 (封装性) //饿汉式 声明时就给他赋值 开辟空间 public static Singlet getS(){ return s; } }
class SingletDemo{ public static void main(String args[]){ //Singlet.s;//拿出该实例 Singlet s1 = Singlet.getS();//拿出该实例 } }
解析:以上用的饿汉式的写法,为了保证有且只有一个对象,那么构造方法私有化,即外界无法调用到,在本类中new出一个对象s 并给他一个getter方法,方便后面的主类中取出这个唯一的实例。
(2) 懒汉式(下面通过一段代码进行解析)
class Singlet2{
private Singlet(){
}
private static Singlet2 s2;
public static Singlet getS2(){
if(s2 ==null){//需要用到时 才创建
s2 = new Singlet2();
}
return s2;
}
class SingletDemo{
public static void main(String args[]){
Singlet2 s3 = Singlet2.getS2();//拿出该实例
}
}
解析:懒汉式和饿汉式不同的点在于,
饿汉式是实例在建立是就给他一个准确内存空间private static Singlet s = new Singlet()。
懒汉式是建立实例时,给他赋一个null,等到要调用getter函数时,再检查实例有无值,无值再给他创立内存空间。
由此可见,饿汉式是线程安全的,虚拟机一开始就加载了这部分内存空间,懒汉式是线程不安全的,需要加同步方法。
实际应用中多用饿汉式。
2.模板模式 通过抽象类去实现 父类提供一个或多个通用方法(需要子类继承) 和 抽象方法(需要子类复写)
下面通过一个简单图形例子来进行解析。(统一打印图形的周长和面积)
abstract class Tuxing{
//以下两个称为钩子方法 用抽象方法 是子类有所差异的,让他们自己去复写
abstract double getArea();
abstract double getZC();
public void print(){//打印方法 是普通方法,子类继承的
System.out.println(getArea());
System.out.println(getZC());
}
}
class juxing extends Tuxing{//矩形,继承图形这个抽象类
private int a;
private int b;
public juxing(int a ,int b){
this.a = a;
this.b = b;
}
double getArea(){
return a * b;
}
double getZC(){
return 2 * a * b;
}
}
class circle extends Tuxing{
private int r;
public circle(int r){
this.r = r;
}
double getArea(){
return 3.14 * r * r;
}
double getZC(){
return 2 * 3.14 * r;
}
}//以下为主方法
public class TempDemo{
public static void main(String args[]){
Tuxing t = new circle(5);//创建圆的图形
t.print();//结果输出元的周长和半径
t = new juxing(2,3);
t.print();
}
}
解析 :用一般方法时 ,往往需要在矩形类或者圆形类中写出打印的代码 这样造成了代码的赘余和重复,采用模板的方式,在父类写出相同的代码方法(即为模板),这样子类就必须继承,用实例去调用,实现功能。
3.简单工厂模式 简单来说 就是讲创建实例 写作一个工厂类 屏蔽子类(工厂中不同的产品)之间的差异
代码分析如下:
在工厂设计中,往往需要有多处相同的改动,简单工厂模式,做到了将多处不同的在一个工厂类中实现,见代码分析
//定义一个手机接口,规定手机的性能协议等一系列问题
public interface ICellphone {
void SendMsg();
}
//以下两个类继承手机接口 复写接口中的SendMsg方法
class Android implements ICellphone{
public void SendMsg() {
System.out.println("安卓手机发送信息");
}
}
class Iphone implements ICellphone{
public void SendMsg() {
System.out.println("苹果手机发送信息");
}
}
//以下是主类
public class FactoryDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
ICellphone p = new Android();
p.SendMsg();//安卓手机发送短信
/*↑传统方法 直接new出自己想要的手机
但此时问题出现 如果要求将安卓改为苹果 就要将上述的new Android()改为new IPhone(),如果此时安卓的个数很多 将会很麻烦*/
/*以上问题的出现 来源于 要造什么手机 的问题
方法:传建一个“工厂” 让它用来造手机 而不是让他们在主类中造 见最下的类*/
p = factory.creat("IPhone");
p.SendMsg();//苹果手机发送短信
p = factory.creat("Android");
}
}
//以下为手机工厂
class factory{
//设为static,方便调用 括号内加参数,方便用户自定义手机型号
public static ICellphone creat(String type){
if(type.equals("Android")){
return new Android();
}else if(type.equals("IPhone")){
return new Iphone();
}
return null;
}
}
以上 这就是简单工厂模式 消除子类之间的差异
缺点在于 每次新添加新的手机型号,就要在工厂类中新加if(type.equals(ooxx)) 做判断
下面用反射机制来实现简单工厂模式,解决上述问题
将工厂模式改为
public class factory {
public static Product getphone(String className) throws Exception, {
return (ICellphone)Class.forName(className).newInstance();
}
}
主类中
p = factory.getphone("包名.IPhone"); //要传进的参数是类的全限定名
p.SendMsg();//苹果手机发送短信
p = factory.getphone("包名.Android");
4.适配器模式
以下用实际例子解析一下
/*
定义一个窗口的标准
*/
interface IWindow{
void max();//最大化
void min();//最小化
void close();//关闭
}
//我自己搞的窗口MyWindow,如果直接继承该接口,所有的方法都要复写,我只想要一个关闭功能就可以了
//此时可以考虑使用 适配器模式
//窗体适配器,
abstract class WindosAdapter implements IWindow//使用abstract修饰,目的是为了保证不准别人来创适配器对象
{
//让适配器去实现标准,并全部覆写方法,但是方法体为空
public void max(){}
public void min(){}
public void close(){}
}
class MyWindow extends WindosAdapter
{
//应当覆写三个方法
//我只关心close方法
public void close(){
System.out.println("关闭我的小窗口");
}
}
class AdapterDemo
{
public static void main(String[] args)
{
IWindow win = new MyWindow();
win.close();
}
}