0%

定义: 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子来中。模板方法使得子类可以在不改变算法接口的情况下,重新定义算法中的某些步骤。

在这章节中作者引出了非常基本的设计原则:

1
1. 别找我,我会找你

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213

模板方法模式是基于继承的代码复用技术,它体现了面向对象的诸多重要思想,是一种使用较为频繁的模式。模板方法模式广泛应用于框架设计中,以确保通过父类来控制处理流程的逻辑顺序(如框架的初始化,测试流程的设置等)。

模板方法模式深度解析(一):模板方法模式概述,模板方法模式结构与实现
模板方法模式深度解析(二):模板方法模式应用实例(银行利息计算模块)
模板方法模式深度解析(三):钩子方法的使用,模板方法模式效果与适用场景

定义: 提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

外观模式的主要目的在于降低系统的复杂程度,在面向对象软件系统中,类与类之间的关系越多,不能表示系统设计得越好,反而表示系统中类之间的耦合度太大,这样的系统在维护和修改时都缺乏灵活性,因为一个类的改动会导致多个类发生变化,而外观模式的引入在很大程度上降低了类与类之间的耦合关系。
引入外观模式之后,增加新的子系统或者移除子系统都非常方便,客户类无须进行修改(或者极少的修改),只需要在外观类中增加或移除对子系统的引用即可。
从这一点来说,外观模式在一定程度上并不符合开闭原则,增加新的子系统需要对原有系统进行一定的修改,虽然这个修改工作量不大。
外观模式中所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统。

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213

外观模式是一种使用频率非常高的设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,使子系统与客户端的耦合度降低,且客户端调用非常方便。

  • 外观模式并不给系统增加任何新功能,它仅仅是简化调用接口。
  • 在几乎所有的软件中都能够找到外观模式的应用,如绝大多数B/S系统都有一个首页或者导航页面,大部分C/S系统都提供了菜单或者工具栏,在这里,首页和导航页面就是B/S系统的外观角色,而菜单和工具栏就是C/S系统的外观角色,通过它们用户可以快速访问子系统,降低了系统的复杂程度。
  • 所有涉及到与多个业务对象交互的场景都可以考虑使用外观模式进行重构。

深入浅出外观模式(一):外观模式概述,外观模式结构与实现
深入浅出外观模式(二):外观模式应用实例(文件加密模块)
深入浅出外观模式(三):抽象外观类,外观模式效果与适用场景

定义: 将一个类的接口,转换成客户期望另一个接口。适配器让原本不兼容的类可以合作无间。

在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。
根据适配器类与适配者类的关系不同,适配器模式可分为对象适配器和类适配器两种,在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系。在实际开发中,对象适配器的使用频率更高。

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213

适配器模式将现有接口转化为客户类所期望的接口,实现了对现有类的复用,它是一种使用频率非常高的设计模式,在软件开发中得以广泛应用,在Spring等开源框架、驱动程序设计(如JDBC中的数据库驱动程序)中也使用了适配器模式。

不兼容结构的协调——适配器模式(一):没有源码的算法库,适配器模式概述
不兼容结构的协调——适配器模式(二):没有源码的算法库的适配器模式解决方案
不兼容结构的协调——适配器模式(三):类适配器,双向适配器
不兼容结构的协调——适配器模式(四):缺省适配

定义: 将请求封装成对象,这可以让你使用不同的请求,队列,或者日志请求来参数化其他对象。命令模式也可以支持撤销操作。

命令模式的本质是对请求进行封装,一个请求对应于一个命令,将发出命令的责任和执行命令的责任分割开。每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行相应的操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213

命令模式是一种使用频率非常高的设计模式,它可以将请求发送者与接收者解耦,请求发送者通过命令对象来间接引用请求接收者,使得系统具有更好的灵活性和可扩展性。在基于GUI的软件开发,无论是在电脑桌面应用还是在移动应用中,命令模式都得到了广泛的应用。

请求发送者与接收者解耦——命令模式(一):自定义功能键,命令模式概述
请求发送者与接收者解耦——命令模式(二):自定义功能键的命令模式解决方案
请求发送者与接收者解耦——命令模式(三):命令队列的实现
请求发送者与接收者解耦——命令模式(四):撤销操作的简单实现
请求发送者与接收者解耦——命令模式(五):请求日志
请求发送者与接收者解耦——命令模式(六):宏命令,命令模式总结

1、为什么要使用单例?

一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。

2、单例的实现

饿汉式

1
2
3
4
5
6
7
8
class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() { }

public static EagerSingleton getInstance() {
return instance;
}
}

饿汉式带来的问题是一上来就会创建对象,一定程度上造成资源的浪费。不过优点在于编写方式简单,容易理解。

懒汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class IdGenerator { 
private AtomicLong id = new AtomicLong(0);
private static IdGenerator instance;
private IdGenerator() {}
public static synchronized IdGenerator getInstance() {
if (instance == null) {
instance = new IdGenerator();
}
return instance;
}
public long getId() {
return id.incrementAndGet();
}
}

双重检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class LazySingleton {
private volatile static LazySingleton instance = null;

private LazySingleton() { }

public static LazySingleton getInstance() {
//第一重判断
if (instance == null) {
//锁定代码块
synchronized (LazySingleton.class) {
//第二重判断
if (instance == null) {
instance = new LazySingleton(); //创建单例实例
}
}
}
return instance;
}
}

双重校验的懒汉式解决了饿汉式一上来就创建对象的问题,一定程度上做到了按需创建。同时双重校验机制只会在第一次创建实例时,有锁的介入,一旦实例创建成功,下次再获取实例就不会进入锁块了。

不过有个问题要注意,CPU 指令重排序可能导致在 LazySingleton 类的对象被关键字 new 创建并赋值给 instance 之后,还没来得及初始化(执行构造函数中的代码逻辑),就被另一个线程使用了。这样,另一个线程就使用了一个没有完整初始化的 LazySingleton 类的对象。要解决这个问题,我们只需要给 instance 成员变量添加 volatile 关键字来禁止指令重排序即可。

静态内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Initialization on Demand Holder
class Singleton {
private Singleton() {
}

private static class HolderClass {
private final static Singleton instance = new Singleton();
}

public static Singleton getInstance() {
return HolderClass.instance;
}

public static void main(String args[]) {
Singleton s1, s2;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();
System.out.println(s1==s2);
}
}

静态内部类方式创建单例是最建议采用的一种方式,代码量较懒汉式少,同时做到了多线程安全,同时没有锁的消耗;对比饿汉式,静态内部类只有在第一次使用的时候才会创建实例,保证了对象按需获取。

instance 的唯一性、创建过程的线程安全性,都由 JVM 来保证。所以,这种实现方法既保证了线程安全,又能做到延迟加载。

枚举

1
2
3
4
5
6
7
8
9
10

public enum IdGenerator {
INSTANCE;
private AtomicLong id = new AtomicLong(0);

public long getId() {
return id.incrementAndGet();
}
}

这种实现方式通过 Java 枚举类型本身的特性,保证了实例创建的线程安全性和实例的唯一性。

3、单例存在哪些问题?

▪ 单例对 OOP 特性的支持不友好
▪ 单例会隐藏类之间的依赖关系
▪ 单例对代码的扩展性不友好
▪ 单例对代码的可测试性不友好
▪ 单例不支持有参数的构造函数

4、单例与静态类的区别?

静态方法无法支持延迟加载

5、有何替代的解决方案?

▪ 静态方法来实现
▪ 通过工厂模式、IOC 容器(比如 Spring IOC 容器)来保证

6、如何理解单例模式中的唯一性?

通常指进程级别保证唯一性

7、如何实现线程唯一的单例?

通过 HashMap 的方式或者 ThreadLocal

8、如何实现集群环境下的单例?

▪ 把这个单例对象序列化并存储到外部共享存储区(比如文件)
▪ 为了保证安全,操作时要考虑加锁,用完后主动释放

9、如何实现一个多例模式?

可以通过 HashMap 限定某个类仅能创建3个对象

10、对于 Java 语言来说,单例类对象的唯一性的作用范围并非进程,而是类加载器(Class Loader),为什么?

Java 中加载一个类是通过 ClassLoaderX + pacakge.class 的方式(双亲委派+类全限定名)唯一确定一个类。而单例指的是一个类对应一个对象。所以可以说 Java 中的单例是类加载器级别的。


参考

定义: 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确制定具体类。

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213

在抽象工厂模式中包含如下几个角色:
● AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
● ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
● AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
● ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。

在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦,抽象工厂模式的这种性质称为“开闭原则”的倾斜性。这也是抽象工厂模式最大的缺点。
“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的,对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:
(1) 增加产品族:对于增加新的产品族,抽象工厂模式很好地支持了“开闭原则”,只需要增加具体产品并对应增加一个新的具体工厂,对已有代码无须做任何修改。
(2) 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了“开闭原则”。
正因为抽象工厂模式存在“开闭原则”的倾斜性,它以一种倾斜的方式来满足“开闭原则”,为增加新产品族提供方便,但不能为增加新产品结构提供这样的方便,因此要求设计人员在设计之初就能够全面考虑,不会在设计完成之后向系统中增加新的产品等级结构,也不会删除已有的产品等级结构,否则将会导致系统出现较大的修改,为后续维护工作带来诸多麻烦。

抽象工厂模式是工厂方法模式的进一步延伸,由于它提供了功能更为强大的工厂类并且具备较好的可扩展性,在软件开发中得以广泛应用,尤其是在一些框架和API类库的设计中,例如在Java语言的AWT(抽象窗口工具包)中就使用了抽象工厂模式,它使用抽象工厂模式来实现在不同的操作系统中应用程序呈现与所在操作系统一致的外观界面。抽象工厂模式也是在软件开发中最常用的设计模式之一。

工厂三兄弟之抽象工厂模式(一):界面皮肤库的初始设计
工厂三兄弟之抽象工厂模式(二):产品等级结构与产品族
工厂三兄弟之抽象工厂模式(三):抽象工厂模式概述
工厂三兄弟之抽象工厂模式(四):界面皮肤库的抽象工厂模式解决方案
工厂三兄弟之抽象工厂模式(五):“开闭原则”的倾斜性,抽象工厂模式总结

定义: 定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

在这章节中作者引出了非常基本的设计原则:

1
1. 依赖抽象,不要依赖具体类。  

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213

工厂方法模式是简单工厂模式的延伸,它继承了简单工厂模式的优点,同时还弥补了简单工厂模式的不足。
工厂方法模式是使用频率最高的设计模式之一,是很多开源框架和API类库的核心模式。

工厂三兄弟之工厂方法模式(一):日志记录器的设计
工厂三兄弟之工厂方法模式(二):工厂方法模式概述
工厂三兄弟之工厂方法模式(三):日志记录器的工厂方法模式解决方案,反射与配置文件
工厂三兄弟之工厂方法模式(四):重载的工厂方法,工厂方法的隐藏,工厂方法模式总结

定义:动态地将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择。

装饰模式和代理模式有点类似,有时甚至容易混淆,倒不是说会把代理当成装饰,而常常会将装饰看作代理。装饰模式是以客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,给爱用继承的人一个全新的设计眼界; 而代理模式则是给一个对象提供一个代理对象,并由代理对象来控制对原有对象的引用。

装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,但不对对象本身的功能进行增强。

装饰者模式类图

装饰者和被装饰者必须是一样的类型,也就是有共同的超类,这是相当关键的地方。在这里,利用继承达到“类型匹配”,而不是利用继承获得“行为”。行为来自装饰者和基础组件,或与其他装饰者之间的组合关系。

1. Java中的装饰者:Java I/O

真实世界的装饰者:Java I/O

装饰java.io类

Java I/O也引出装饰者模式的一个“缺点”:利用装饰者模式,常常造成设计中有大量的小类,数量实在太多了,可能会造成使用此API程序员的困扰。

2. Android中的装饰者:Context

Android中Context类图

从图中我们可以看出,ContextImpl和ContextWrapper继承自Context,ContextWrapper内部包含有Context类型的mBase对象,mBase具体指向的是ContextImpl。ContextImpl提供了很多功能,但是外界需要使用并拓展ContextImpl的功能,因此设计上使用了装饰模式,ContextWrapper是装饰类,它对ContextImpl进行包装,ContextWrapper主要是起了方法传递作用,ContextWrapper中几乎所有的方法实现都是调用ContextImpl的相应方法来实现的。

ContextThemeWrapper、Service和Application都继承自ContextWrapper,这样他们都可以通过mBase来使用Context的方法,同时它们也是装饰类,在ContextWrapper的基础上又添加了不同的功能。

ContextThemeWrapper中包含和主题相关的方法(比如: getTheme方法),因此,需要主题的Activity继承ContextThemeWrapper,而不需要主题的Service则继承ContextWrapper。

定义: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。

在这章节中作者引出了非常基本的设计原则:

1
2
1. 为交互对象之间的松耦合设计而努力。  
找出程序中会变化的方面,然后将其和固定不变的方面想分离

后续补充更多的内容:android中涉及的,java中涉及的观察者模式

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213
文中以多人联机对战游戏案例展开,稳重包含了观察者模式结构图,解决方案结构图。同时介绍了JDK对观察者模式的支持
对象间的联动——观察者模式(一):多人联机对战游戏的设计
对象间的联动——观察者模式(二):观察者模式概述
对象间的联动——观察者模式(三):多人联机对战游戏的观察者模式解决方案
对象间的联动——观察者模式(四):JDK对观察者模式的支持
对象间的联动——观察者模式(五):观察者模式与Java事件处理
对象间的联动——观察者模式(六):观察者模式与MVC,观察者模式总结

定义: 策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

head first书中在第一章引出策略模式,个人猜测
第一由于策略模式定义简单,容易理解;
第二策略模式是非常基本的模式,使用频率很高的缘故。

在这章节中作者引出了非常基本的设计原则:

1.封装变化
2.针对接口编程,而不是针对实现编程
3.多用组合,少用继承

这三个设计原则基本却非常重要,在我们的工作编程中需时刻提醒自己,检查并重构自己的代码。

下面的内容转载自:http://blog.csdn.net/lovelion/article/details/17517213
文中以电影票案例展开,介绍的非常详细。包含了策略模式结构图,解决方案结构图…
算法的封装与切换——策略模式(一):电影票打折方案
算法的封装与切换——策略模式(二):策略模式概述
算法的封装与切换——策略模式(三):电影票打折方案的策略模式解决方案
算法的封装与切换——策略模式(四):策略模式的两个典型应用,策略模式总结