笔者带你剖析23种设计模式之01

《笔者带你剖析23种设计模式01》

 

前言

其实就笔者个人而言,并不是很情愿单独开系列博文来针对设计模式进行讲解,原因有2点,首先设计模式早几年已经有大量的专业书籍进行阐述,以及互联网上丰富参考文献等;其次,大量的第三方开源组件、中间件内部已经广泛使用设计模式,底层码砖的开发人员实际工作中接触到几率不大。那么为什么笔者又要做一些不情愿的事情呢?这是因为企业中过多的小家伙们总是希望硬生生的把某一种设计模式强塞到项目中来,纯粹是为了设计模式而设计模式,违背初衷,设计的意义何在?

 

希望大家记住,良好的系统架构往往是伴随着业务的发展逐步演化而来,并不是设计出来,架构师真正能够做到的是在项目设计之初,尽可能面向接口编程、遵循类的单一原则,善用设计模式,这样才能够使我们的项目具有更好的伸缩性、维护性、扩展性,以及复用性。

 

目录

一、开篇;

二、创建型——简单工厂模式;

三、创建型——工厂方法模式;

四、创建型——抽象工厂模式;

五、创建型——创建者模式;

六、创建型——原型模式;

七、创建型——单例模式;

八、题外话——实现更好的解耦,Spring IOC工厂外围化;

 

一、开篇

你必须了解的是,学习和掌握设计模式,并不是为了在企业中显示你的成就感和卓越感,因此,切记不要再生搬硬套的将任何一种设计模式强塞在你的项目中,否则事与愿违,违背初衷,说严重点,你可能将会得不偿失。设计模式其实简单来说仅仅只是一种思想,一种方法论,它并不是指某一种具体的技术,也就是说,任何一种使用OOP开发的系统(Java、C++、Python、C#、Ruby等),只要你想使你的项目具有更好的伸缩性、维护性、扩展性,以及复用性,那么尽可能面向接口编程、遵循类的单一原则,善用设计模式,将会事半功倍。

 

图A-1 设计模式分类

 

本着打算利用3章系列博文的篇幅来对Gof提出的23种设计模式做详细的讲解,因此笔者将这一系列的设计模式划分为了3大类,如图A-1所示。

 

二、创建型——简单工厂模式

相信每一位技术牛人都曾经有过一段较为青涩的人生时光,笔者将那个阶段称之为菜鸟期。在那个阶段,大部分开发人员往往都会在代码中直接使用new关键字创建出一个类的对象实例,当然从语法、语义上来看并没有任何错误,只是从领域模型这个大的方向来分析,其每一个组件都应该具备独立性,当然笔者知道这在实际的开发过程中几乎不可能做到,系统解耦是一个漫长的过程,只是如果不从一点一滴做起,你的系统将不具备任何复用性,因为逻辑耦合度太高,换句话来说,只有首先明确每一个类的单一原则才能够更好的为后续架构调整提供便利。

 

既然类需要具备单一原则,那么在一个类的内部使用关键字new创建出一个新的对象必然是不合理的,因此创建型模式中提供了3种工厂模式来帮助大家解决这个问题。从严格意义上来说,Gof所提出来的23种设计模式之中其实并不包括简单工厂模式,之所以笔者把它也放在23种设计模式内进行讲解是因为其特有的简易性,在大部分应用场景中,简单工厂模式确实能够解决一部分问题,因此笔者首先拿它最为开篇无疑是最明智的选择。

 

简单工厂模式也可以称之为静态工厂模式,它的目的就是为了能够将对象的创建过程与实际的调用过程进行分离,这样一来,就体现出了类的单一原则,并且系统各个组件之间的耦合度也随之降低了。那么简单工厂模式如何设计呢?如图A-2所示。

图A-2 简单工厂模式类图

 

如上图所示,简单工厂模式的核心就是提供一个静态工厂,所有的对象创建过程全部在这个静态工厂内完成,以此分离对象的创建过程和调用过程。当然面向接口编程是前提,静态工厂返回中testMethod()方法的返回类型为抽象类型的接口,因为接口可以有不同的实现,工厂自然根据里氏替换原则创建出对应的派生类实现。简单工厂模式的核心代码:

public class AnimalFactory {
	public static Animal getAnimal(String type) {
		Animal animal = null;
		switch (type) {
		case "tiger":
			animal = new Tiger();
			break;
		case "pig":
			animal = new Pig();
		}
		return animal;
	}
}

 

相信大家似乎已经尝到了点系统设计的甜头,那么笔者不得不提醒大家,简单工厂模式只是最简单的一种工厂模式,从严格意义上来讲,它并不属于Gof所提出的23种设计模式中的任何一种,尽管简单工厂模式的优点是简易性以及可以分离对象的创建过程和调用过程使类单一化,但是其缺点就是纵向维护成本太高,因为如果有新的类型的对象实例需要进行创建,那么静态工厂内的switch语句将会变得非常冗余,维护成本也就随之升高,不利于后期复用。

 

 三、创建型——工厂方法模式

剖析完简单工厂模式后,接下来我们再来看工厂方法模式。尽管简单工厂模式的易用性可以满足绝大多数应用场景,但是一旦对象关系变得复杂化,或者对象过多时,单凭一个静态工厂是不可能完成所有对象的创建的,尽管你可以这么做,但是是否需要稍微考虑下维护成本?

 

工厂方法模式可以认为是简单工厂的升级版本,它弥补了简单工厂模式的不足,能够胜任对象关系更加复杂,以及更多对象需要进行创建的应用场景。简单来说,工厂方法模式需要一个抽象的大工厂作为基类,然后不同对象由实现了基类工厂的子工厂负责进行对应创建。打个比方,程序中一共有10个对象需要进行创建,那么编号为1-10的工厂分别负责创建对应的对象实例,这样一来,即分离了对象的创建和调用过程,同样也降低了简单工厂模式在实际开发过程中的纵向维护成本,可谓一举两得。如图A-3所示。

图A-3 工厂方法模式类图

 

如上图所示,工厂方法模式的核心就是提供了一个抽象的工厂基类,不同的子工厂实现这个抽象的大工厂后,分别负责创建与之对应的对象实例,从而降低了简单工厂模式的纵向维护成本,以及更好的提升了类的单一原则。工厂方法模式的核心代码:

public interface AnimalFactory {
	public Animal getAnimal();
}
public class TigerFactory implements AnimalFactory {
	@Override
	public Animal getAnimal() {
		return new Tiger();
	}
}
public class PigFactory implements AnimalFactory {
	@Override
	public Animal getAnimal() {
		return new Pig();
	}
}

 

在此大家需要注意,工厂方法模式的优点既是它的缺点,尽管它可以很好的解决简单工厂模式所面临的弊端,但是如果程序中有>=100个以上的类需要创建其对象实例时,难道需要编写100个对应的子工厂?这样一来尽管降低了纵向维护成本,但是随着子工厂数量的井喷式增长,程序的横向维护成本也随之上升

 

四、创建型——抽象工厂模式

抽象工厂模式应该算是所有工厂模式中逻辑上最难理解的一个,它出现的目的只有一个,就是解决简单工厂模式和工厂方法模式遇到的问题(更大程度上是看做工厂方法模式的升级),即能在最大程度上遵循类的单一设计原则,同样又能够降低工厂方法模式所带来的横向维护成本等问题。

 

那么抽象工厂模式是如何设计的呢?简单来说,如果按照之前在工厂方法模式中的需求,有10个类甚至更多的类需要由子工厂进行创建对象实例时,我们可以根据业务分类将相互关联的一组类型归纳在一起统一由一个子工厂进行维护并创建(同工厂方法模式一样,也需要继承一个抽象的工厂基类),这样一来,工厂类的数目与需要进行创建对象实例的数目自然就不成正比,大大降低了横向维护成本。

 

五、创建型——创建者模式

如果说工厂模式的作用是为了将对象的创建过程与调用过程进行分离,那么创建者模式的作用就是更进一步,将对象的创建过程、组装过程与调用过程进行分离。细心的读者应该发现了,笔者由工厂类返回的对象实例,调用者在调用之前,是需要在其内部按照里氏替换原则进行对象组装的,按照类的单一原则来说,调用者的职责仅仅只是负责调用对象的某一个方法,执行相应的逻辑行为,对象的组装过程自然不应该由调用者负责,这便是创建者模式的意义。创建者模式的核心代码:

public class AnimalTest {
	public @Test void testMethod() {
		new Director(new PigFactory()).getType();
		new Director(new TigerFactory()).getType();
	}
	class Director {
		AnimalFactory factory;
		Director(AnimalFactory factory) {
			this.factory = factory;
		}
		void getType() {
			if (null != factory) {
				Animal animal = factory.getAnimal();
				animal.type();
			}
		}
	}
}

 

一旦我们在设计过程中使用工厂模式+创建者模式的组合后,就可以成功的将对象的创建过程、组装过程与调用过程进行有效分离。这样一来,调用者的职责就更加清晰,与调用无关的所有操作,比如对象的创建交由工厂负责,而组装过程则交由创建者负责。

 

猜你喜欢

转载自gao-xianglong.iteye.com/blog/2224683