Singleton单例模式是最简单的设计模式,它的主要作用是保证在程序执行生命周期中,使用了单类模式的类仅仅能有一个实例对象存在。
java设计模式(1)
先简单的介绍下设计模式吧:是一种解决这个问题的一种行之有效的思想;用于解决特定环境下、反复出现的特定问题的解决方式。
那为什么我们须要学习设计模式呢?
1、设计模式都是一些相对优秀的解决方式,非常多问题都是典型的、有代表性的问题,学习设计模式,我们就不用自己从头来解决这些问题,相当于在巨人的肩膀上。复用这些方案就可以,站的高看到远,就是要站在巨人的肩膀上把他们踩下去。嘿嘿。
2、设计模式已经成为专业人士的经常使用词汇。不懂不利于交流。能让你变得非常牛逼哦。
3、能让你设计的系统更加专业,让系统有更好的架构,能让你变成大牛哦。
以下介绍几种设计模式:
一、单例
假设要求一个类的内存中仅仅有一个类的话能够採用单例解决。
1、思路:
①、假设其它程序能够任意用new创建该类对象,那么就无法控制个数。
因此。不让其它程序用new创建该类的对象。
②、既然不让其它程序new该类对象。那么该类在自己内部就要创建一个对象。否则该类就永远无法创建对象了。
③、该类将创建的对象对外(整个系统)提供,让其它程序获取并使用。
2、步骤:
①、将该类中的构造函数私有化。
②、在本类中创建一个本类对象。
③、定义一个方法,返回值类型是本类类型。让其它程序通过该方法就能够获取到该类对象。
3、代码:
①、饿汉式:
class Single{ private static final Single s = new Single(); private Single(){ } public static Single getInstance(){ return s; } }②、懒汉式:(单例的延迟载入方式)
class Single2 { private static Single2 s = null; private Single2(){ } public static Single2 getInstance() { //(PS:假设要考虑线程安全的话。应该这样写:public static synchronized Single2 getInstance(){) if(s==null) s=new Single2(); return s; } }4、单例变形(多例)
①、缓存在单例中的使用(“单例+缓存”技术)
要求:缓存在编程中使用非常频繁。有着非常关键的数据,它能够帮助程序实现以空间换取时间。通常被设计成整个应用程序所共享的一个空间。现要求实现一个用缓存存放单例对象的类。
说明:该缓存中能够存放多个该类对象。每一个对象以一个key值标识,key值同样时所訪问的是同一个单例对象
代码:
import java.util.HashMap; import java.util.Map; public class A { //定义一个缓存(集合),用来存放数据的容器 private static Map<String,A> map = new HashMap<String,A>(); public static A getInstance(String key){ A a = map.get(key); //推断a是否存在,不存在则是null if(a==null){ a = new A();//新建一个对象 map.put(key, a);//把新对象放入缓存 } return a; } }②、单例变形——多例模式(“单例+缓存+控制实例个数”技术)
要求:把上面缓存的单例实现,做成一个能够控制对象个数的共享空间,供整个应用程序使用。在缓存中维护指定个数的对象,每一个对象的key值由该类内部指定,有外部请求时直接返回当中一个对象出去。说明:相当于维护一个指定数量的对象池,当请求个数超过控制的总数时,開始循环反复使用 。
代码:
import java.util.HashMap; import java.util.Map; public class Multiple { private static Map<Integer,Multiple> map = new HashMap<Integer,Multiple>(); private static int num=1; private static int count=3;//控制实例的个数:3 public static Multiple getInstance(){ Multiple m = map.get(num); if(m==null){ m = new Multiple(); map.put(num, m); } num++; //假设num超过所控制的个数。则又一次设为1。以进行循环反复使用缓存中的对象 if(num>count){ num=1; } return m; } public static void main(String[] args) { //測试案例 Multiple m1 = Multiple.getInstance(); System.out.println("m1:::"+m1); Multiple m2 = Multiple.getInstance(); System.out.println("m2:::"+m2); Multiple m3 = Multiple.getInstance(); System.out.println("m3:::"+m3); Multiple m4 = Multiple.getInstance(); System.out.println("m4:::"+m4); Multiple m5 = Multiple.getInstance(); System.out.println("m5:::"+m5); } }
二、工厂
1、我能够在java程序开发的时候讲究面向接口编程,须要把隐藏具体的实现类的时候能够採用project设计模式。
2、工厂类的命名规范:***Factory;单例工厂方法的命名规范:getInstance()。
3、工厂的本质是“选择实现”
4、工厂、接口和实现类之间的技术边界:工厂仅仅负责选择实现,实现类才做真正的实现。而接口是限定究竟实现什么东西和返回什么东西。三者之间分工明白、各负其责。
5、通过代码来具体的介绍:
①、接口Api:
//接口Api public interface Api { public abstract String t1(); }
②、两个实现类Imp1和Imp2:(都是实现了接口Api)
class Imp1:
//实现类Impl public class Impl implements Api { @Override public String t1() { return "11111111111111"; //这里是仅仅是測试数据而已 } }class Imp2:
//实现类Imp2 public class Impl2 implements Api { @Override public String t1() { return "222222"; } }③、工厂DepFactory :
//工厂DepFactory public class DepFactory { public static Api createApi(){ return new Impl2();//通过配置文件+类反射,让我们的程序依赖字符串 } }④、測试类(使用类):
public class Client { public static void main(String[] args) { Api obj = DepFactory.createApi();//new Impl(); String str = obj.t1(); System.out.println(str); } }
三、值对象
1、在java开发过程中,须要来回交换大量的数据的时候能够採用值对象设计模式。
2、值对象的本质是“封装数据”
3、主要的编写步骤:
第1步:写一个类,实现可序列化(假设以后数据是往数据库里存的,那么能够不序列化。节省资源)
第2步:私有化全部属性。保持一个默认构造方法(public无參)
第3步:为每一个属性提供get()、set()方法(假设是boolean型变量,最好把get改成is)
第4步:推荐覆盖实现equals()、hashCode()和toString()方法
4、代码实现:
import java.io.Serializable; //值对象 public class UserModel implements Serializable { //实现序列化 //私有化全部属性 private String id,name,address; private boolean man; public UserModel(String name){ this.name = name; } public UserModel(){ } //给全部属性提供get(),set()方法 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public boolean isMan() { return man; } public void setMan(boolean man) { this.man = man; } //hashCode和equals一般仅仅用“主键”来生成 //覆盖hashCode(),equals(),toString()方法 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; UserModel other = (UserModel) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } @Override public String toString() { return "UserModel [id=" + id + ", name=" + name + ", address=" + address + ", man=" + man + "]"; } }
四、装饰模式
1、在不正确原有对象类进行改动的基础上,须要给一个或多个已有的类对象提供增强额外的功能的时候能够採用装饰设计模式。
2、引例:
要求:写一个MyBufferedReader类,使它能够对字符流(如FileReader、InputStreamReader和PipedReader等)进行功能增强:
(1) 提供带缓冲的myRead()方法,对原有的read()方法进行增速。
(2)提供一个能够每次读取一行字符的myReadLine()方法。
代码:
import java.io.FileReader; import java.io.IOException; public class MyBufferedReader{ private FileReader r;//封装(这里能够依据须要改成InputStreamReader和PipedReader等) private char[] buf = new char[1024]; private int count=0;//记录当前缓冲区中字符的个数 private int pos=0;//数组元素的下标。当前所读的位置 //构造函数 public MyBufferedReader(FileReader r){ this.r = r; } //读单个字符函数 public int myRead() throws IOException{ if(count==0){ count = r.read(buf); pos=0; } if(count==-1){ return -1;//表示已经读完了最后一个元素 } char ch = buf[pos]; pos++; count--; return ch; } //读一行字符函数 public String myReadLine() throws IOException{ StringBuilder sb = new StringBuilder(); int ch=0; while((ch=myRead())!=-1){ if(ch=='\r'){ continue; } if(ch=='\n'){ return sb.toString();//遇到回车就返回这行字符串 } sb.append((char)ch); } //这里是保证最后一行没有回车的字符串的输出 if(sb.length()!=0) return sb.toString(); return null; } //抛异常函数 public void close() throws IOException{ r.close(); } }把上面代码结合在别的类使用:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class TestMyBufferedReader { //main函数 public static void main(String[] args) { try { //仅仅读一个字符 readTest();//原始測试 myReadTest();//我们自己写的加强測试 //读一行 readLineTest();//原始測试 myReadLineTest();//我们自己写的加强測试 } catch (IOException e) { e.printStackTrace(); } } //-------------------------------------------//
<span style="white-space:pre"> </span>//API原始方法 private static void readTest() throws IOException { FileReader r = new FileReader("a.txt"); BufferedReader br = new BufferedReader(r); int ch=0; while((ch=br.read())!=-1){ System.out.print((char)ch); } br.close(); r.close(); }
<span style="white-space:pre"> </span>//我们自己写的加强版 private static void myReadTest() throws IOException { FileReader r = new FileReader("a.txt"); MyBufferedReader br = new MyBufferedReader(r); int ch=0; while((ch=br.myRead())!=-1){ System.out.print((char)ch); } br.close(); r.close(); } //-------------------------------------------// <pre name="code" class="java"><span style="white-space:pre"> </span>//API原始方法private static void readLineTest() throws IOException {FileReader r = new FileReader("a.txt");BufferedReader br = new BufferedReader(r);String line=null;while((line=br.readLine())!=null){System.out.println(line);}br.close();r.close();}
<span style="white-space:pre"> </span><pre name="code" class="java"><span style="white-space:pre"> </span>//我们自己写的加强版private static void myReadLineTest() throws IOException {FileReader r = new FileReader("a.txt");MyBufferedReader br = new MyBufferedReader(r);String line=null;while((line=br.myReadLine())!=null){System.out.println(line);}br.close();r.close();}}
- 本文已收录于以下专栏:
- Java学习日志
posted on 2018-01-11 20:22 yjbjingcha 阅读(398) 评论(0) 编辑 收藏 举报