设计模式(Design Patterns)
专注于为中小企业提供网站建设、做网站服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业原州免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了成百上千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
——可复用面向对象软件的基础
设
计模式(Design
pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代
码可靠性。
毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用
设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决
方案,这也是它能被广泛应用的原因。
一、设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。
例子:
单例模式(Singleton)
单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
首先我们写一个简单的单例类:
[java] view plaincopy
public class Singleton {
/* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;
/* 私有构造方法,防止被实例化 */
private Singleton() {
}
/* 静态工程方法,创建实例 */
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
/* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */
public Object readResolve() {
return instance;
}
}
第一个
public interface RandomNumberListener {//接口
public void numberChanged(double d);
}
第二个
public class Consol implements RandomNumberListener{
@Override
public void numberChanged(double d) {
System.out.println(d);
}
}
第三个
public class SwingWindow
extends JFrame
implements RandomNumberListener{//观察者
private JLabel label = new JLabel();
public SwingWindow(){
this.getContentPane().add( label);
this.setSize(300,200);
this.setVisible(true);
}
@Override
public void numberChanged(double d) {
label.setText(String.valueOf(d));
}
}
第四个
public class RandomNumber {//业务
private double r;
private ListRandomNumberListener listeners = new ArrayListRandomNumberListener();
//添加所有观察者
public void addRandomNumberListener(RandomNumberListener lis){
listeners.add(lis);
}
public void random(){
r = Math.random();
//数据发生改变,通知所有的观察者
for (RandomNumberListener lis : listeners) {
lis.numberChanged(r);
}
}
}
第五个
public class Test {
public static void main(String[] args) throws InterruptedException{
RandomNumber rn = new RandomNumber();
SwingWindow sw = new SwingWindow();
Consol c = new Consol();
rn.addRandomNumberListener(sw);
rn.addRandomNumberListener(c);
while(true){
rn.random();
Thread.sleep(new Random().nextInt(3000)+1000L);
}
}
}
.饿汉式单例类
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 {
//私有的默认构造子
private Singleton1() {}
//已经自行实例化
private static final Singleton1 single = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}
2.懒汉式单例类
//懒汉式单例类.在第一次调用的时候实例化
public class Singleton2 {
//私有的默认构造子
private Singleton2() {}
//注意,这里没有final
private static Singleton2 single=null;
//静态工厂方法
public synchronized static Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
//对懒汉式单例的改进(错误的改进)
//实际上,只有在第一次创建对象的时候需要加锁,之后就不需要了 ,这样可以提升性能
public synchronized static Singleton2 getInstance() {
if (instance == null) {
synchronized(instance){ //锁住当前实例对象
if(instance == null){
instance = new Singleton2();
}
}
}
return instance;
}
错误原因:
aA、B线程同时进入了第一个if判断
bA首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();
c由于JVM内部的优化机制,JVM先画出了一些分配给Singleton实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块。
dB进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序。
e此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。
正确改进(使用内部类):
JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的,JVM能够帮我们保证instance只被创建一次,
并且会保证把赋值给instance的内存初始化完毕,这样我们就不用担心上面的问题。
同时该方法也只会在第一次调用的时候使用互斥机制,这样就解决了低性能问题
public?class?Singleton?{??
??
/*?私有构造方法,防止被实例化?*/??
private?Singleton(){
}
/*?此处使用一个内部类来维护单例?*/??
private?static?class?SingletonFactory?{??
private?static?Singleton?instance?=?new?Singleton();??
}
/*?获取实例?*/??
public?static?Singleton?getInstance()?{??
return?SingletonFactory.instance;??
}
/*?如果该对象被用于序列化,可以保证对象在序列化前后保持一致?*/??
public?Object?readResolve()?{??
return?getInstance();??
}
}
其实说它完美,也不一定,如果在构造函数中抛出异常,实例将永远得不到创建,也会出错????
第二种改进:
因为我们只需要在创建类的时候进行同步,所以只要将创建和getInstance()分开,
单独为创建加synchronized关键字,也是可以的
public class Singleton {
private static Singleton instance=null;
private Singleton(){}
private static synchronized void Init(){
if(instance==null)
instance=new Singletion();
}
public static Singleton getInstance(){
if(instance==null){
Init();
}
return instance;
}
}
3.登记式单例类
import java.util.HashMap;
import java.util.Map;
//登记式单例类.
//类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
private static MapString,Singleton3 map = new HashMapString,Singleton3();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保护的默认构造子
protected Singleton3(){}
//静态工厂方法,返还此类惟一的实例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println("name == null"+"---name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
//一个示意性的商业方法
public String about() {
return "Hello, I am RegSingleton.";
}
public static void main(String[] args) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
/**
* @author 不落的太阳(Sean Yang aka ShortPeace)
* @version 1.0
* @since jdk 1.8
*
*/
public class DecoratorFileWriter extends FileWriter {
public DecoratorFileWriter(String fileName) throws IOException {
super(fileName);
}
@Override
public String getEncoding() {
return super.getEncoding();
}
@Override
public void write(int c) throws IOException {
super.write(c);
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
super.write(cbuf, off, len);
}
@Override
public void write(String str, int off, int len) throws IOException {
String decoratorStr = str.replaceAll(" ", "");
super.write(decoratorStr, off, len);
}
@Override
public void flush() throws IOException {
super.flush();
}
@Override
public void close() throws IOException {
super.close();
}
@Override
public void write(char[] cbuf) throws IOException {
super.write(cbuf);
}
@Override
public void write(String str) throws IOException {
String decoratorStr = str.replaceAll(" ", "");
super.write(decoratorStr);
}
@Override
public Writer append(CharSequence csq) throws IOException {
return super.append(csq);
}
@Override
public Writer append(CharSequence csq, int start, int end) throws IOException {
return super.append(csq, start, end);
}
@Override
public Writer append(char c) throws IOException {
return super.append(c);
}
}