zoukankan      html  css  js  c++  java
  • java之 ------ 几种常见的简单设计模式

    前言:

    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。用于解决特定环境下、反复出现的特定问题的解决方式。使用设计模式是为了可重用代码、让代码更easy被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的。设计模式使代码编制真正project化,设计模式是软件project的基石。如同大厦的一块块砖石一样。项目中合理的运用设计模式能够完美的解决非常多问题,每种模式在如今中都有相应的原理来与之相应,每个模式描写叙述了一个在我们周围不断反复发生的问题。以及该问题的核心解决方式。这也是它能被广泛应用的原因。(引用---点击打开链接


    一、单例模式(SingletonPattern

    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方法加synchronizedkeyword。

    所以该为以下这句就可以。

    public static synchronized Single2 getInstance();
    可是,synchronizedkeyword锁住的是这个对象,这种使用方法,在性能上会有所下降。由于每次调用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;
    	}
    }
    

    二、工厂模式(Factory Pattern

    工厂模式: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

    三、值对象模式(Value Object Pattern

    值对象模式:简单的说就是封装数据。方便各个模块之间的数据的交流。

    ★ 主要的编写步骤:

    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 + "]";
    	}
    	
    }
    

    四、装饰模式(Decorator Pattern

    装饰模式:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。

    它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

    例:写一个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=='
    '){
    				continue;
    			}
    			if(ch=='
    '){
    				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;
    	}
    }
    








  • 相关阅读:
    Javascript一天学完系列(四)函数上下文bind &call
    Javascript一天学完系列(三)JavaScript面向对象
    Javascript一天学完系列(二)Callbacks回调函数
    Python(切片)
    水果篮子(母函数)
    判断链表是否有环
    链表部分逆置
    Python(List和Tuple类型)
    HDU1426(DFS)
    HDU4474(数位BFS)
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7001805.html
Copyright © 2011-2022 走看看