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;
    	}
    }
    








  • 相关阅读:
    Postman使用教程
    CAD和ArcGIS转换 矢量配准
    SAP CRM Advanced search和Simple search里Max hit表现行为的差异
    SAP CRM Product simple search的启用步骤
    如何快速定位SAP CRM订单应用(Order Application)错误消息抛出的准确位置
    如何动态修改SAP CRM WebClient UI表格栏的宽度
    如何在SAP CRM WebClient UI里创建web service并使用ABAP消费
    如何处理SAP CRM Web Service错误
    如何使用SAP CRM WebClient UI实现一个类似新浪微博的字数统计器
    如何开启SAP CRM基于WORD模板创建附件的功能
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7001805.html
Copyright © 2011-2022 走看看