标签:java设计模式 单例模式 工厂模式 值对象模式 装饰模式
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。用于解决特定环境下、重复出现的特定问题的解决方案。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。(引用---点击打开链接)
a、单例模式:是一种常见的设计模式。为了保证一个类在内存中只能有一个对象。
思路:1、如果其他程序能够随意用new创建该类对象,那么就无法控制个数。因此,不让其他程序用new创建该类的对象。
2、既然不让其他程序new该类对象,那么该类在自己内部就要创建一个对象,否则该类就永远无法创建对象了。
3、该类将创建的对象对外(整个系统)提供,让其他程序获取并使用。
步骤:1、将该类中的构造函数私有化。
2、在本类中创建一个本类对象。
3、定义一个方法,返回值类型是本类类型。让其他程序通过该方法就可以获取到该类对象。
单例模式中又有:饿汉式和懒汉式两种
1、饿汉式:不管你需不需要,都在类内部直接先生成一个对象。因为构造方法为私有的,所以外面无法new新的对象,只能通过getInstance来获得这个唯一的对象,从而实现单例模式
/*饿汉式*/ public class Single { private static final Single s=new Single(); private Single(){ } public static Single getInstance(){ return s; } }2、懒汉式:与饿汉式不同之处在于,不是直接生成一个对象,而是在需要对象是才会生成,也就是只有当调用getInstance这个方法是才会产生这个唯一对象。(也可以说是单例的延迟加载方式)
/*懒汉式*/ public class Single2 { private static Single2 s; private Single2(){ } public static Single2 getInstance(){ if(s==null){ s = new Single2(); } return s; } }这个类可以满足基本要求,但是,像这样毫无线程安全保护的类,如果我们把它放入多线程的环境下,肯定就会出现问题了(问题就是假如有多个线程同时到达if(s==null)时,这个条件都成立,那么就会产生多个对象了,就违背了我们的本意),如何解决?我们首先会想到对getInstance方法加synchronized关键字。所以该为下面这句即可。
public static synchronized Single2 getInstance();但是,synchronized关键字锁住的是这个对象,这样的用法,在性能上会有所下降,因为每次调用getInstance(),都要对对象上锁,事实上,只有在第一次创建对象的时候需要加锁,之后就不需要了,所以,这个地方需要改进:
public static synchronized Single2 getInstance(){ if(s==null){ synchronized (s) { <span style="white-space:pre"> </span>if (s == null) { <span style="white-space:pre"> </span> s = new Single2(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} } return s; }看上去写的很好,但在自己运行时,就会发现还是有错误,虽然知道是线程的原因,却没有深究。大概知道那么回事。看看大神的准确解答:在Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就可能出错了。
b、单例变形-----多例 (“单例+缓存”技术)
★ 缓存在单例中的使用
缓存在编程中使用很频繁,有着非常重要的作用,它能够帮助程序实现以空间换取时间,通常被设计成整个应用程序所共享的一个空间,现要求实现一个用缓存存放单例对象的类。
说明:该缓存中可以存放多个该类对象,每个对象以一个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; } }
工厂模式:Java程序开发讲究面向接口编程,通过建立一个工厂类,隐藏具体的实现类。
首先创建公共接口:
public interface Api { public abstract String t1(); }然后创建实现类:
public class Impl implements Api { @Override public String t1() { return "11111111111111"; } }
public class Impl2 implements Api { @Override public String t1() { return "222222"; } }最后创建工厂类:
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); } }结果:222222
值对象模式:简单的说就是封装数据,方便各个模块之间的数据的交流。
★ 基本的编写步骤:
1、写一个类,实现可序列化(如果以后数据是往数据库里存的,那么可以不序列化,节省资源)
2、私有化所有属性,保持一个默认构造方法(public无参)
3、为每个属性提供get()、set()方法(如果是boolean型变量,最好把get改成is)
4、推荐覆盖实现equals()、hashCode()和toString()方法
public class UserModel implements Serializable { private String id,name,address; private boolean man; public UserModel(String name){ this.name = name; } public UserModel(){ } 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一般只用“主键”来生成 @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 + "]"; } }
装饰模式:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
例:写一个MyBufferedReader类,使它能够对字符流(如FileReader、InputStreamReader和PipedReader等)进行功能增强:
(1) 提供带缓冲的myRead()方法,对原有的read()方法进行增速;
(2)提供一个能够每次读取一行字符的myReadLine()方法。
思路:一般要实现一个类的功能就想到继承这个类。但是这里要实现多个类的功能,而继承只能继承一个。那就不得不写多个类了,这样就会显得臃肿。
另一种方法就是封装,不用继承,但是缺点和上面一样。
所以想到把二者结合起来,从而达到要求。也就是装饰模式。
import java.io.IOException; import java.io.Reader; public class MyBufferedReader extends Reader{ //※※※让加强类融入到体系中 private Reader r;//封装 private char[] buf = new char[1024]; private int count=0;//记录当前缓冲区中字符的个数 private int pos=0;//数组元素的下标,当前所读的位置 public MyBufferedReader(Reader 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(); } @Override public int read(char[] cbuf, int off, int len) throws IOException { return 0; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:java设计模式 单例模式 工厂模式 值对象模式 装饰模式
原文地址:http://blog.csdn.net/u011479875/article/details/47816985