前言:

设计模式(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=='\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之 ------ 几种常见的简单设计模式的更多相关文章

  1. [转载 ]五种常见的 PHP 设计模式

    五种常见的 PHP 设计模式 策略模式 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因为这个设计模 ...

  2. java讲讲几种常见的排序算法(二)

    java讲讲几种常见的排序算法(二) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 堆排序 思路:构建一个小顶堆,小顶堆就是棵二叉树,他的左右孩子均大于他的根节点( ...

  3. java讲讲几种常见的排序算法

    java讲讲几种常见的排序算法(一) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 以数组array={6,3,20,8,15,1}为例 冒泡排序 思路:从第0个到 ...

  4. Java中9种常见的CMS GC问题分析与解决

    1. 写在前面 | 本文主要针对 Hotspot VM 中"CMS + ParNew"组合的一些使用场景进行总结.重点通过部分源码对根因进行分析以及对排查方法进行总结,排查过程会省 ...

  5. 你值得关注的几种常见的js设计模式

    前言 潜水了一段时间,今天空闲时间复盘下之前的知识点,聊聊 js 几种常见的设计模式. 掌握 JavaScript 中常见的一些设计模式,对我们书写规范性代码,可维护性代码有很大的帮助. ps:最近在 ...

  6. 【转】五种常见的 PHP 设计模式

    工厂模式 最初在设计模式 一书中,许多设计模式都鼓励使用松散耦合.要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程.在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为完 ...

  7. 五种常见的 PHP 设计模式

    设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Gamma.Richard Helm.Ralph Johnson 和 John Vlissides Design(俗称 “四人帮”).所 ...

  8. 转:Java实现几种常见排序方法

    日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序,甚至还有基数排序.鸡尾酒排序.桶排序.鸽巢排序.归并排序等. 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一 ...

  9. [转]五种常见的 PHP 设计模式

    FROM : http://www.ibm.com/developerworks/cn/opensource/os-php-designptrns/ 设计模式 一书将设计模式引入软件社区,该书的作者是 ...

随机推荐

  1. MySQ学习笔记之十 NULL值处理

    这是MySQL一大特殊之处. 概念上.NULL意味着"没有值"或"未知值",且它被看作有点与众不同的值. 为了測试NULL.你不能使用算术比較运算符比如=.&l ...

  2. sass03 变量、样式导入

    demo1.scss @import "css.css"; //导入css文件 @import "http://ss/xx"; //导入css文件 @impor ...

  3. spark 数据预处理 特征标准化 归一化模块

    #We will also standardise our data as we have done so far when performing distance-based clustering. ...

  4. 基于深度学习的病毒检测技术无需沙箱环境,直接将样本文件转换为二维图片,进而应用改造后的卷积神经网络 Inception V4 进行训练和检测

    话题 3: 基于深度学习的二进制恶意样本检测 分享主题:全球正在经历一场由科技驱动的数字化转型,传统技术已经不能适应病毒数量飞速增长的发展态势.而基于沙箱的检测方案无法满足 APT 攻击的检测需求,也 ...

  5. Laravel-数据库队列

    Laravel-数据库队列 标签(空格分隔): php 介绍 Laravel队列为不同的后台队列服务提供统一的API,例如Beanstalk,Amazon SQS, Redis,甚至其他基于关系型数据 ...

  6. C++字节对齐与结构体大小计算

    转载注明出处:http://pppboy.blog.163.com/blog/static/30203796201082494026399/ 感谢原创博主的辛勤成果. 说明: 结构体的sizeof值, ...

  7. Kubernetes安装配置(包括master和node)

    部署Kubernetes云计算平台,至少准备两台服务器,此处为4台,包括一台Docker仓库: Kubernetes Master节点:192.168.124.20 Kubernetes Node1节 ...

  8. uptime---系统总共运行时间和系统的平均负载

    uptime命令能够打印系统总共运行了多长时间和系统的平均负载.uptime命令可以显示的信息显示依次为:现在时间.系统已经运行了多长时间.目前有多少登陆用户.系统在过去的1分钟.5分钟和15分钟内的 ...

  9. 监控memcached服务

    #!/bin/bash #监控memcached服务 printf "del key\r\n" | nc 127.0.0.1 11211 &>/dev/null #使 ...

  10. CJOI 05新年好 (最短路+枚举)

    CJOI 05新年好 (最短路+枚举) 重庆城里有n个车站,m条双向公路连接其中的某些车站.每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费 ...