java设计模式(1)-------单例,工厂,值对象,装饰模式

      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程序开发的时候讲究面向接口编程,需要把隐藏具体的实现类的时候可以采用工程设计模式。

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


版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-11 01:36:08

java设计模式(1)-------单例,工厂,值对象,装饰模式的相关文章

java设计模式之单例设计模式

设计模式:解决某一类问题最行之有效的方法. java中23种设计模式. 单例设计模式:解决一类在内存中只存在一个对象. Runtime()方法就是单例设计模式进行设计的. 解决的问题:保证一个类在内存中的对象唯一性. 比如:多程序读取一个配置文件时,建议配置文件封装成对象.会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,就需要该配置文件对象在内存中是唯一的. 1.为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象. 2.还为了让其他程序可以访问该类对象,只好在本类中自定

java设计模式--解决单例设计模式中懒汉式线程安全问题

首先写个单例,懒汉模式: public class SingleDemo { private static SingleDemo s = null; private SingleDemo(){} public static SingleDemo getInstance(){ if(s == null){ s = new SingleDemo(); } return s; } } 写个测试类: public class ThreadDemo3 { public static void main(S

java设计模式_single(单例设计模式)

设计模式:解决某一类问题最行之有效的方法,java中有23种设计模式 一.单例设计模式概述: 1.解决一个类在内存中只有一个对象(保证一个类仅有一个实例,并提供一个访问他的全局访问点)  2.要保证对象的唯一: 1.为了避免其他程序过多的建立该类对象,先禁制其他程序建立该类对象 2.为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象 3.为了 方便其他程序对自定义对象的访问,可以对外提供一些访问方式 3.代码实现步骤: 1.将构造函数私有化 2.在类中创建一个本类对象 3.给外部提供

java设计模式之单例

写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上线后还可以帮助你分析数据.但是Java原生带有的System.out.println()方法却很少在真正的项目开发中使用,甚至像findbugs等代码检查工具还会认为使用System.out.println()是一个bug. 为什么作为Java新手神器的System.out.println(),到了真正项目开发当中会被唾弃呢?其实只要细细分析,你就会发现它的很多弊端.比如不可控制,所有的日志都会在项目上线后照常打印,从而降低运

Java设计模式之一 单例设计模式

1.什么叫设计模式: 设计模式的概念首先来源于其它行业:建筑业,在早起建房子的时候,肯定是经验缺乏.显得杂乱无序的,这就会造成很多问题,在行业发展过程,通过不断的经验积累,前辈们针对这些问题提出了合理解决方案,这就是设计模式,参照设计模式往往可以解决很多问题,在计算机编程方面,也会出现类似问题,所以牛人们把这些解决问题的方案进行归类和总结,形成了面向对象编程的23种设计模式. 2.单例模式(特点): Java中单例模式定义:"一个类有且仅有一个实例,并且自行实例化向整个系统提供."通过

PHP设计模式 二 (单例 工厂 注册)

单例模式 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案. 数据库单例示例: <?php namespace Components; class Database { protected static $db; private function __construct(){ //单列模式

Java设计模式之单例设计模式(Singleton)

单例设计模式 单例模式在日常开发中用的也比较多,顾名思义就是一个类的对象在整个系统中只能有一个 优点: 1.单例模式会阻止其他对象实例化其自己的单例对象副本,从而确保所有对象都访问唯一实例 2.由于在整个系统中指存在一个实例对象,避免了频繁的创建和销毁对象,因此可以节约系统资源 3.避免了对共享资源的多重占用 4.自行创建这个单例对象,避免使用时再去创建 缺点: 1.单例模式没有抽象层,所以扩展性比较差 2.不适用于变化的对象,如果同一类型的对象需要在不同的场景下使用,单例就会引起数据的错误 3

java设计模式之单例设计模式和多例设计模式

单例设计模式:构造方法私有化,在类的内部定义static属性和方法,利用static方法来取得本类的实例化对象:无论外部产生多少个实例化对象,本质上只有一个实例化对象 饿汉式单例设计 class Singleton{ private static final Singleton INSTANCE = new Singleton();//产生一个实例化对象 private Singleton(){}//封装构造方法 public static Singleton getInstance(){ re

设计模式:简单工厂和单例工厂

1 <?php 2 /** 3 * 纯粹工厂类 4 */ 5 /*class Factory { 6 public static function getOBJ($class_name) { 7 include_once './'.$class_name.'.class.php'; 8 return new $class_name; //可变类 9 } 10 } 11 */ 12 13 /** 14 * cun工厂类 15 */ 16 class Factory { 17 /* 18 生产单例对

笔记:Java中的单例设计模式

之前接触过单例模式,当初不明白这样的设计用意,今天特地研究了下java中的单例设计模式的用处及用法. 单例模式:单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.一个类有且仅有一个实例,并且自行实例化向整个系统提供. 单例模式的用处:一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务:一个系统只能有一个窗口管理器或文件系统:一个系统只能有一个计时工具或ID(序号)生成器.如在Windows中就只能打开一个任务管理器.如果不使用机制对窗口对象进行唯一化,将