在Java编程当中往往让编码无从下手的地方便是如何确定方向,选择合适的方法都会让工作的效率极大的提高,不光在Java,在所有面向对象语言当中都有一些固定的方法去解决问题,经过一段 时间的沉淀和 改变,这些设计模式成为编程出发点。
在一般的情况下设计模型分为创建型 结构型 和行为型。而这三大类再次细分之后又分为如下图

而以上的二十三种是面向对象当中所有的设计模式,这里针对一些常用的设计模式进行简述,详细请参考《设计模式》或者百度。
工厂模式
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来。工厂模式可以细分为:
1、简单工厂模式 :不利于 生产系列产品
2、工厂方法模式 :称为多边形性工厂
3、抽象工厂模式 :生产产品族,不利于产生新的产品
1、简单工厂:
又称为静态工厂方法模式 核心是一个具体的类
优点:如果客户端需要某种产品,只要向工厂类发送请求,由该类负责所有产品的生产
缺点:如果新增具体产品的时候,需要改动工厂类的代码。
2、工厂方法模式
工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法里不再只由一个工厂类决定,那一个产品类应当被实例化,这个决定被交给 抽象类的子类去做 核心是一个抽象工厂类。
优点:解决简单工厂模式有新产品加入时,需要更改原有工厂类的问题,本模式党章一旦有新产品加入只需要创建与之对应的具体工厂类。
缺点:系统中存在大量的具体工厂类,每个工厂类只能支撑一个子产品
3、抽象工厂模式:
解决工厂方法模式缺陷。
如:
package xin.factory;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Properties;
abstract class Factory {
public abstract OnePlus one();
}
/*
* class Get32G extends Factory { public OnePlus one() { return new T32G(); } }
*
* class Get64G extends Factory { public OnePlus one() { return new T64G(); } }
*
* class Get128G extends Factory { public OnePlus one() { return new T128G(); }
* }
*/
public class AbstractFactory {
public static void main(String[] args) {
String name = "";
try (BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("src/xin/factory/set.txt")))) {
name = br.readLine();
} catch (Exception e) {
e.printStackTrace();
}
try {
Properties sks = new Properties();
sks.load(new FileInputStream("src/bin.properties"));
String key = sks.getProperty(name);
OnePlus tk = (OnePlus) (Class.forName(key).newInstance());
tk.Virtual();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package xin.factory;
abstract class ProSmart{}
abstract class ProVovi{}
abstract class AbstractPhone{
public abstract ProSmart SmartT1();
public abstract ProVovi vovi();
public abstract OnePlus one();
}
public class Product {}
package xin.factory;
public abstract class OnePlus {
public abstract void Virtual();
}
class T32G extends OnePlus{
public void Virtual(){
System.out.println("This is 32G!");
}
}
class T64G extends OnePlus{
public void Virtual(){
System.out.println("This is 64G!");
}
}
class T128G extends OnePlus{
public void Virtual(){
System.out.println("This is 128G!");
}
}
单例模式
说起来比较特殊,它是一种常用的软件设计模式,几乎任何一门面向对象语言都有这个模式的实现方法,在它的核心结构当中只包含了一个被称为单例的特殊类,你通过这个类只能创建一个实例,在实际生活当中这种唯一性是有很大的用途。
在Java语言当中,单例模式是这样定义的:一个类有且只有一个实例,并且自行实例化向整个系统提供,在线程部分学习到了锁机制,这样可以利用锁机制来实现。由于这种特殊的模式单例模式的优缺点都是十分明显的 :
优点:
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
缺点:
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
这里借用 菜鸟教程(链接:http://www.runoob.com/design-pattern/singleton-pattern.html ) 的一个Demo来实现单利模式:

根据上面的类图
public class SingleObject {
// 创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
// 让构造函数为 private,这样该类就不会被实例化
private SingleObject() {
}
// 获取唯一可用的对象
public static SingleObject getInstance() {
return instance;
}
public void showMessage() {
System.out.println("Hello World!");
}
}
public class SingletonPatternDemo {
public static void main(String[] args) {
//不合法的构造函数
//编译时错误:构造函数 SingleObject() 是不可见的
//SingleObject object = new SingleObject();
//获取唯一可用的对象
SingleObject object = SingleObject.getInstance();
//显示消息
object.showMessage();
}
}
单利模式的几种实现方式:
懒汉式,线程安全
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。
是否 Lazy 初始化:是
是否多线程安全:是
实现难度:易
描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉式
是否 Lazy 初始化:否
是否多线程安全:是
实现难度:易
描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
它基于 classloder 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
双检锁/双重校验锁(DCL,即 double-checked locking)
JDK 版本:JDK1.5 起
是否 Lazy 初始化:是
是否多线程安全:是
实现难度:较复杂
描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
也可以使用枚举来实现单例模式,可以有效防止序列化对单例的影响。
暂时先介绍这两种,其实还是在看重单利模式的设计 思想,其中牵扯多线程和序列化问题值得注意,而其他设计模式以后会陆续写入。