转载请保留原文链接: http://dashidan.com/article/java/basic/20.html
软件设计领域的四位世界级大师Gang Of Four (GoF):Erich Gamma, Richard Helm, Ralph Johnson,John Vlissides合著了一本非常著名的书《Design Patterns - Elements of Reusable Object-Oriented Software》翻译的中文名为《设计模式:可复用面向对象软件的基础》.书中提出了23种基本设计模式,从理论高度提炼并规范了设计模式,对面向对象软件设计产生了巨大影响.
① 设计模式简介
总体来说设计模式分为三大类:
创建型模式,共五种:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式.
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式.
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式.
有些设计模式我个人认为,不是很具象, 就像星座一样抽象概念居多,导致应用场景不明确. 所以不希望他们占用我过多的脑容量和时间.只挑选几个含金量高, 模型具象, 应用场景广泛的模式来介绍. 以下这几个都是非常值得花时间去熟悉的模式.
② 单例模式
单例模式即是只产生一个对象的模式.在Java中,每次使用new
关键字, 就会产生一个新的对象. 有时我们需要只有一个对象产生, 比如一些管理类, 全局管理其它模块时, 这个管理类适合采用单例模式.
普通的单例模式分为2种, 懒汉式和饿汉式.懒汉式比较懒, 用到的时候才创建对象, 饿汉式不讲理, 你用不用我都创建好放着.
普通单例模式的秘籍:
* 将构造函数定义为私有private
, 只能在本类中创建, 不能被继承.
* 通过private
和static
关键字定义一个私有并且静态的本类实例对象, 保证内存中只有1个实例, 并且只有本类能调用.
* 公开一个获得本类实例的静态方法, 来获取这个实例, 保证每次得到的实例都是同一个, 来实现单例模式.
列出4种常用的单例模式的写法, 推荐第4种. 第4种是通过内部类实现, 高效且线程安全. 记住这个好了, 其他的可以忘.
1.懒汉式
/**
* 懒汉式单例模式
*/
class Singleton1 {
private static Singleton1 singleton1;
private Singleton1() {
}
public static Singleton1 getInstance() {
if (null == singleton1) {
singleton1 = new Singleton1();
}
return singleton1;
}
}
2.饿汉式
/**
* 饿汉式单例模式
*/
class Singleton2 {
private static Singleton2 singleton2 = new Singleton2();
private Singleton2() {
}
public static Singleton2 getInstance() {
return singleton2;
}
}
3.线程安全的懒汉式
/**
* 线程安全懒汉式单例模式
*/
class Singleton3 {
private static Singleton3 singleton3;
private Singleton3() {
}
public static synchronized Singleton3 getInstance() {
if (null == singleton3) {
singleton3 = new Singleton3();
}
return singleton3;
}
}
4.内部类线程安全单例模式
这种方式利用java的final
关键字特性, 一旦赋值无法改变.线程安全,效率高推荐方式.
/**
* 内部类线程安全单例模式
*/
class Singleton4 {
private static class SingletonHolder {
public final static Singleton4 instance = new Singleton4();
}
public static Singleton4 getInstance() {
return SingletonHolder.instance;
}
}
③ 工厂模式
工厂模式本质是通过条件语句,根据不同的条件创建不同的对象.通常情况下, 产生的对象继承自同一个父类, 工厂类提供的方法返回的类型为父类对象类型.达到对象封装的作用.
代码示例:
package com.dashidan.lesson19;
/**
* 大屎蛋教程网-dashidan.com
* <p>
* Java教程基础篇: 19.Java设计模式
* 工厂模式
*/
public class Demo2 {
public static void main(String[] args) {
/** 传入需要生产的产品类型*/
Product product = Factory.getProduct(1);
/** 打印产品信息*/
product.info();
}
}
/**
* 工厂模式
* 根据不同的类型,生产不同的产品
*/
class Factory {
public static Product getProduct(int type) {
switch (type) {
case 1:
return new Product1();
case 2:
return new Product2();
}
return null;
}
}
/**
* 产品的父类是抽象类,提供一个info方法
*/
abstract class Product {
public abstract void info();
}
/**
* 产品Product1继承自父类Product
*/
class Product1 extends Product {
@Override
public void info() {
System.out.println("Product1 info.");
}
}
/**
* 产品Product2继承自父类Product
*/
class Product2 extends Product {
@Override
public void info() {
System.out.println("Product2 info.");
}
}
输出:
Product1 info.
④ 观察者模式
观察者模式(也称为发布(publish)-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式).是一个非常棒的降低代码耦合度的方式.
观察者模式的秘籍:
* 观察者在发布者对象上注册消息侦听, 加入消息侦听列表
* 发布者遍历消息侦听列表, 调用观察者方法处理消息
* 不同的观察者对象通常继承同一个观察者接口, 通过接口方法统一处理
通常用在一对多或者多对多的场景中, 一个对象数据变化了, 需要通知其他对象的场景. 比如ActionScript3
语言底层的事件冒泡机制, 就是采用观察者模式设计.
代码示例:
package com.dashidan.lesson19;
import java.util.ArrayList;
/**
* 大屎蛋教程网-dashidan.com
* <p>
* Java教程基础篇: 19.Java设计模式
* 观察者模式
*/
public class Demo3 {
public static void main(String[] args) {
/** 初始化发布者和观察者*/
Publisher publisher = new Publisher();
Observer1 observer1 = new Observer1();
Observer2 observer2 = new Observer2();
/** 加入2个观察者到发布者的消息侦听队列*/
publisher.addObserver(observer1);
publisher.addObserver(observer2);
/** 通知观察者*/
publisher.notifyAllObserver();
}
}
/**
* 发布者
*/
class Publisher {
/**
* 发布者的消息侦听队列
*/
ArrayList<IObserver> observers = new ArrayList<>();
/**
* 加入消息侦听队列
*/
public void addObserver(IObserver iObserver) {
System.out.println("加入观察者");
observers.add(iObserver);
}
/**
* 通知侦听队列中所有的观察者
*/
public void notifyAllObserver() {
for (IObserver iObserver : observers) {
System.out.println("通知观察者");
iObserver.action();
}
}
}
/**
* 观察者接口
*/
interface IObserver {
void action();
}
/**
* 观察者Observer1类
*/
class Observer1 implements IObserver {
@Override
public void action() {
System.out.println("Observer1 action.");
}
}
/**
* 观察者Observer2类
*/
class Observer2 implements IObserver {
@Override
public void action() {
System.out.println("Observer2 action.");
}
}
输出:
加入观察者
加入观察者
通知观察者
Observer1 action.
通知观察者
Observer2 action.