单例模式(Singleton pattern)用于 Runtime,Calendar 和其他的一些类中。
工厂模式(Factory pattern)被用于各种不可变的类如 Boolean,像 Boolean.valueOf。
观察者模式(Observer pattern)被用于 Swing 和很多的事件监听中。
装饰器设计模式(Decoratordesign pattern)被用于多个 Java IO 类中。
单例模式重点在于在整个系统上共享一些创建时较耗资源的对象。整个应用中只维护一个特定类实例,它被所有组件共同使用。Java.lang.Runtime 是单例模式的经典例子。从 Java5 开始你可以使用枚举(enum)来实现线程安全的单例。
//懒汉 线程不安全(多线程不能正常运行)
public class SingletonOne {
private static SingletonOne singletonOne;
private SingletonOne(){
}
public static SingletonOne getInstance(){
if(singletonOne == null){
singletonOne = new SingletonOne();
}
return singletonOne;
}
}
//懒汉 线程安全 效率很低 能在多线程很好的工作
public class SingletonTwo {
private static SingletonTwo instance;
private SingletonTwo(){
}
public static synchronized SingletonTwo getInstance(){
if(instance == null){
instance = new SingletonTwo();
}
return instance;
}
}
//饿汉
/**
* 这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,
* 在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,
* 这时候初始化instance显然没有达到lazy loading的效果。
* */
public class SingletonThree {
private static SingletonThree instance = new SingletonThree();
private SingletonThree(){
}
public static SingletonThree getInstance(){
return instance;
}
}
//双重锁校验
public class SingletonFive {
private volatile static SingletonFive instance;
private SingletonFive(){
}
public static SingletonFive getInstance(){
if(instance == null){
synchronized (SingletonFive.class){
if(instance == null ){
instance = new SingletonFive();
}
}
}
return instance;
}
}
定义:在软件系统中,对象不是孤立存在的,一个对象行为的改变可能会导致一个或多个其他与之存在依赖关系的对象行为发生改变。
在多人联机对战的游戏中,多个玩家可以加入同一个战队组成联盟,当战队中的某一成员受到敌人攻击时将给所有其它盟友发送通知,盟友收到通知后做出响应。
AllyControlCenter:指挥部类
package 设计模式.观察者模式;
import java.util.LinkedList;
import java.util.List;
abstract class AllyControlCenter {
protected String allyName; //战队名称
protected List<IObserver> players = new LinkedList<IObserver>();
public String getAllyName() {
return allyName;
}
public void setAllyName(String allyName) {
this.allyName = allyName;
}
//注册方法
public void Join(IObserver obs){
System.out.println(obs.getName() + "加入" + this.allyName + "战队!");
players.add(obs);
}
//注销方法
public void Quit(IObserver obs){
System.out.println(obs.getName() + "退出" + this.allyName + "战队!");
}
//声明抽象通知方法
public abstract void NotifyObserver(String name);
}
ConcreteAllyControlCenter:具体指挥部类
package 设计模式.观察者模式;
public class ConcreteAllyControlCenter extends AllyControlCenter {
public ConcreteAllyControlCenter(String allyName){
System.out.println(allyName + "战队组建成功!");
System.out.println("-------------------------");
this.allyName = allyName;
}
//实现通知方法
@Override
public void NotifyObserver(String name) {
System.out.println(this.allyName + "战队紧急通知,盟友" + name + "遭受攻击!!");
//遍历观察者集合,调用每一个盟友的支援方法
for (Object obs:players) {
if(!((IObserver)obs).getName().equals(name)){
((IObserver)obs).Help();
}
}
}
}
IObserver:抽象观察者类
package 设计模式.观察者模式;
abstract class IObserver {
private String Name;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
abstract void Help(); //声明支援盟友的方法
abstract void BeAttacked(AllyControlCenter acc); //声明遭受攻击方法
}
Player:战队成员类
package 设计模式.观察者模式;
public class Player extends IObserver {
private String Name;
@Override
public String getName() {
return Name;
}
@Override
public void setName(String name) {
this.Name = name;
}
public Player(String name){
this.Name = name;
}
//支援方法的实现
@Override
void Help() {
System.out.println("坚持住," + this.Name + "来救你了!!");
}
//遭受攻击方法实现
@Override
void BeAttacked(AllyControlCenter acc) {
System.out.println(this.Name + "被攻击!!");
acc.NotifyObserver(Name);
}
}
Test:测试类
package 设计模式.观察者模式;
public class Test {
public static void main(String[] args) {
//定义战队
AllyControlCenter acc;
acc = new ConcreteAllyControlCenter("复仇者联盟");
//定义盟友
IObserver player1,player2,player3,player4;
player1 = new Player("钢铁侠");
player2 = new Player("绿巨人");
player3 = new Player("蜘蛛侠");
player4 = new Player("黑寡妇");
acc.Join(player1);
acc.Join(player2);
acc.Join(player3);
acc.Join(player4);
//某成员遭受攻击,出发联动
player1.BeAttacked(acc);
}
}
结果:
复仇者联盟战队组建成功!
-------------------------
钢铁侠加入复仇者联盟战队!
绿巨人加入复仇者联盟战队!
蜘蛛侠加入复仇者联盟战队!
黑寡妇加入复仇者联盟战队!
钢铁侠被攻击!!
复仇者联盟战队紧急通知,盟友钢铁侠遭受攻击!!
坚持住,绿巨人来救你了!!
坚持住,蜘蛛侠来救你了!!
坚持住,黑寡妇来救你了!!
Process finished with exit code 0
到这里观察者模式的简单应用例子就结束了
优点:
(1)可以现表示层和数据逻辑层的分离,定义了稳定的消息更新传送机制;
(2)在观察目标和观察者之间建立了一个抽象的耦合,观察目标只要维持一个抽象的观察者集合,无须了解具体的观察者。
(3)观察者模式符合开闭原则,增加新的具体观察者无需修改原有的系统代码。
缺点:
(1)如果在观察者和观察目标之间存在循环依赖,观察目标会触发他们进行循环调用,可能会导致系统崩溃。
(2)如果一个观察目标对象有很多直接和间接的观察者,将所有观察者都通知到会花费很多时间。
定义:是一种用于替代继承的技术,通过一种无需定义子类的方法的方式给对象动态的增加职责,使用对象之间的关联关系取代类之间的继承关系。
某公司开发一套图形界面构件库,该构建库提供了大量的基本构件,如窗体、文本框、列表框等,由于在使用该构件库的时候,用户经常要定制一些特殊的显示效果,比如滚动条的窗体、带黑色边框的文本框等。因此经常需要对该构件库进行扩展以增强其功能。
VisualComponent:抽象界面构件类
package 设计模式.装饰器模式;
abstract class VisualComponent {
public abstract void Display();
}
Window:窗体类
package 设计模式.装饰器模式;
public class Window extends VisualComponent {
@Override
public void Display() {
System.out.println("显示窗体!");
}
}
TextBox:文本框类
package 设计模式.装饰器模式;
public class TextBox extends VisualComponent {
@Override
public void Display() {
System.out.println("显示文本框!");
}
}
ListBox:列表框类
package 设计模式.装饰器模式;
public class ListBox extends VisualComponent {
@Override
public void Display() {
System.out.println("显示列表框!");
}
}
ComponentDecorator:构件装饰类
package 设计模式.装饰器模式;
public class ComponentDecorator extends VisualComponent {
private VisualComponent component;
//注入抽象构件类型对象
public ComponentDecorator(VisualComponent component){
this.component = component;
}
@Override
public void Display() {
component.Display();
}
}
ScrollBarDecorator:滚动条装饰类
package 设计模式.装饰器模式;
public class ScrollBarDecorator extends ComponentDecorator {
public ScrollBarDecorator(VisualComponent component) {
super(component);
}
@Override
public void Display(){
this.SetScrollBar();
super.Display();
}
public void SetScrollBar(){
System.out.println("为构件添加滚动条");
}
}
BlackBorderDecorator:黑色边框装饰类
package 设计模式.装饰器模式;
public class BlackBorderDecorator extends ComponentDecorator {
public BlackBorderDecorator(VisualComponent component) {
super(component);
}
@Override
public void Display(){
this.SetBlackBorder();
super.Display();
}
public void SetBlackBorder(){
System.out.println("为构件添加黑色边框");
}
}
Test:测试类
package 设计模式.装饰器模式;
public class Test {
public static void main(String[] args){
VisualComponent componentW,componentSB,componentBB;
componentW = new Window();
componentSB = new ScrollBarDecorator(componentW); //为窗体添加滚动条
componentBB = new BlackBorderDecorator(componentW);//为窗体添加黑色边框
componentSB.Display();
componentBB.Display();
}
}
结果:
为构件添加滚动条
显示窗体!
为构件添加黑色边框
显示窗体!
Process finished with exit code 0
优点:
(1)扩展一个对象的功能,装饰器模式比继承更加灵活,不会导致类的个数大量增加。
(2)通过一种动态方式来扩展一个对象的功能。
(3)对一个对象进行多次装饰,创造很多不同行为的组合。
(4)具体构件类和具体装饰类可以独立变化。
在这里我会从简单工厂到工厂方法模式再到抽象工厂一一简述。
定义:是工厂模式最简单的设计模式之一,定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
Product:
package 设计模式.工厂模式.简单工厂模式;
abstract class Product {
public void MethodSame(){
System.out.println("公共方法的实现");
}
//声明抽象业务方法
public abstract void MethodDiff();
}
ConcreteProductA:
package 设计模式.工厂模式.简单工厂模式;
public class ConcreteProductA extends Product{
@Override
public void MethodDiff() {
System.out.println("ConcreteProductA业务方法的实现");
}
}
ConcreteProductB:
package 设计模式.工厂模式.简单工厂模式;
public class ConcreteProductB extends Product {
@Override
public void MethodDiff() {
System.out.println("ConcreteProductB业务方法的实现");
}
}
Factory:
package 设计模式.工厂模式.简单工厂模式;
public class Factory {
//静态工厂方法
public static Product GetProduct(String arg){
Product product = null;
if(arg.equals("A")){
product = new ConcreteProductA();
}else if(arg.equals("B")){
product = new ConcreteProductB();
}
return product;
}
}
Test:
package 设计模式.工厂模式.简单工厂模式;
public class Test {
public static void main(String[] args){
Product product;
product = Factory.GetProduct("A");
product.MethodSame();
product.MethodDiff();
}
}
结果:
公共方法的实现
ConcreteProductA业务方法的实现
Process finished with exit code 0
优点:
(1)简单工厂模式包含必要的判断逻辑,可以决定什么时候创建哪一个产品类的实例。
(2)客户端不需要知道所创建的具体产品类的类名。
(3)通过配置文件,可以不修改客户端的代码来增加新的具体产品类。
缺点:
(1)由于工厂类集中所有产品的创建逻辑,职责过重,一旦出错整个系统都要受影响。
(2)使用简单工厂肯定会增加类的个数。
(3)系统扩展困难。
(4)简单工厂模式使用静态工厂的方法,造成工厂角色无法形成基于继承的等级结构。
定义:工厂方法是简单工厂的延申,继承了简单工厂的优点,弥补了简单工厂的缺点。定义一个用于创建对象的接口,但是让子类决定哪个类实例化。
某系统运行日志记录器可以通过多种途径保存系统的运行日志,比如通过文件记录或数据库记录。
Logger:日志记录器接口
package 设计模式.工厂模式.工厂模式;
public interface Logger {
void WriteLog();
}
DatabaseLogger :数据库日志记录器
package 设计模式.工厂模式.工厂模式;
public class DatabaseLogger implements Logger {
@Override
public void WriteLog() {
System.out.println("数据库日志记录");
}
}
FileLogger:文件日志记录器
package 设计模式.工厂模式.工厂模式;
public class FileLogger implements Logger{
@Override
public void WriteLog() {
System.out.println("文件日志记录");
}
}
LoggerFactory:日志记录器工厂接口
package 设计模式.工厂模式.工厂模式;
public interface LoggerFactory {
Logger CreateLogger();
}
FileLoggerFactory:文件日志记录器工厂类
package 设计模式.工厂模式.工厂模式;
public class FileLoggerFactory implements LoggerFactory {
@Override
public Logger CreateLogger() {
Logger logger = new FileLogger();
return logger;
}
}
DatabaseLoggerFactory:数据库日志记录器工厂类
package 设计模式.工厂模式.工厂模式;
public class DatabaseLoggerFactory implements LoggerFactory {
@Override
public Logger CreateLogger() {
Logger logger = new DatabaseLogger();
return logger;
}
}
Test:测试类
package 设计模式.工厂模式.工厂模式;
public class Test {
public static void main(String[] args){
LoggerFactory loggerFactory;
Logger logger;
loggerFactory = new FileLoggerFactory();
logger = loggerFactory.CreateLogger();
logger.WriteLog();
}
}
结果:
文件日志记录
Process finished with exit code 0
优点:
(1)工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类被实例的这一细节。
(2)基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。
(3)在系统中加入新产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,只要添加一个具体工厂和具体产品即可。
缺点:
(1)添加新产品时,需要编写新的具体产品类,还要提供与之对应的具体工厂类,系统中类的个数将成对增加,一定程度上增加了系统的复杂度。
(2)考虑到系统的扩展性,需要引入抽象层,增加了系统的抽象性和理解难度。
定义:抽象工厂模式是常用的创建型设计模型之一,它比工厂方法模式的抽象程度更高。在工厂模式中,每个具体工厂只要生产一种具体产品,但在抽象工厂中,一个具体工厂可以生产一组相关的具体产品,这样的一组产品称为产品族。
某公司要开发一套界面皮肤库。用户在使用时可以通过菜单来选择皮肤,不同的皮肤将提供视觉效果不同的按钮文本框组合框等界面元素。如下图所示。
Button:按钮接口
package 设计模式.工厂模式.抽象工厂;
public interface Button {
void Display();
}
SpringButton:Spring按钮类
package 设计模式.工厂模式.抽象工厂;
public class SpringButton implements Button {
@Override
public void Display() {
System.out.println("显示浅绿色按钮");
}
}
SummerButton:
package 设计模式.工厂模式.抽象工厂;
public class SummerButton implements Button {
@Override
public void Display() {
System.out.println("显示浅蓝色的按钮");
}
}
TextField:
package 设计模式.工厂模式.抽象工厂;
public interface TextField {
void Display();
}
SpringTextField:
package 设计模式.工厂模式.抽象工厂;
public class SpringTextField implements TextField {
@Override
public void Display() {
System.out.println("显示绿色边框文本框");
}
}
SummerTextField:
package 设计模式.工厂模式.抽象工厂;
public class SummerTextField implements TextField {
@Override
public void Display() {
System.out.println("显示蓝色边框文本框");
}
}
ComboBox:
package 设计模式.工厂模式.抽象工厂;
public interface ComboBox {
void Display();
}
SpringComboBox:
package 设计模式.工厂模式.抽象工厂;
public class SpringComboBox implements ComboBox {
@Override
public void Display() {
System.out.println("显示绿色边框组合框");
}
}
SummerComboBox:
package 设计模式.工厂模式.抽象工厂;
public class SummerComboBox implements ComboBox {
@Override
public void Display() {
System.out.println("显示蓝色边框组合框");
}
}
SkinFactory:
package 设计模式.工厂模式.抽象工厂;
public interface SkinFactory {
Button CreateButton();
TextField CreateTextField();
ComboBox CreateComboBox();
}
SpringSkinFactory:
package 设计模式.工厂模式.抽象工厂;
public class SpringSkinFactory implements SkinFactory {
@Override
public Button CreateButton() {
return new SpringButton();
}
@Override
public TextField CreateTextField() {
return new SpringTextField();
}
@Override
public ComboBox CreateComboBox() {
return new SpringComboBox();
}
}
SummerSkinFactory:
package 设计模式.工厂模式.抽象工厂;
public class SummerSkinFactory implements SkinFactory {
@Override
public Button CreateButton() {
return new SummerButton();
}
@Override
public TextField CreateTextField() {
return new SummerTextField();
}
@Override
public ComboBox CreateComboBox() {
return new SummerComboBox();
}
}
Test:
package 设计模式.工厂模式.抽象工厂;
public class Test {
public static void main(String[] args){
SkinFactory factory;
Button bt;
TextField tf;
ComboBox cb;
factory = new SpringSkinFactory();
bt = factory.CreateButton();
tf = factory.CreateTextField();
cb = factory.CreateComboBox();
bt.Display();
tf.Display();
cb.Display();
}
}
结果:
显示浅绿色按钮
显示绿色边框文本框
显示绿色边框组合框
Process finished with exit code 0
优点:
(1)抽象类隔离了具体类的生成,使得客户端不需要知道什么被创建。
(2)当一个产品族中的多个对象被设计成一起工作时,他能保证客户端只使用同一个产品族中的对象。
(3)增加新的产品族很方便。
缺点:
增加产品等级结构麻烦,需要对原系统进行巨大的修改,甚至要修改抽象层,违背了开闭原则。