前言
有一些奉为经典的东西,不能只看一遍,要多看,每次都能有新的认识。
技术容易学会,但是思想不是一朝一夕就能参透的。设计模式对于框架设计和提高代码质量作用很大。前段时间在看设计模式方面的书籍,一段时间后发现理解不深刻,掌握也不好。所以打算对每个模式都写一篇文章,不仅可以加深认识,还能方便大家学习。
以GOF的《设计模式》的内容为主,参考其他的书籍和博客,再结合自己的认识,用容易理解的语言来阐述。
本文属于基础篇,目的就是讲清楚他是什么,怎么用。
介绍23种设计模式,分类如下:
创建型模式:
工厂方法
抽象工厂
建造者模式
单例模式
原型模式
结构性模式:
适配器模式
桥接模式
组合模式
装饰着模式
外观模式
享元模式
代理模式
行为型模式:
策略模式
模版方法
观察者模式
迭代模式
责任链模式
命令模式
备忘录模式
状态模式
访问者模式
中介者模式
解释器模式
设计模式1——工厂方法
1 解释
1.1 定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
1.2 举例
大家请看下面的小故事:
1. 很久以前出现了汽车这么一个工具,大家非常喜欢,但是没有工厂来生产制造,想要汽车就得自己制造。
2. 几年后有了工厂这个东西,他专门来生产汽车,只要你提供的汽车材料他能生产,你就能得到想要的汽车。与原来相比,方便了许多,省去了各种复杂的制造过程。
3. 慢慢的,人们的需求越来越多,工厂为了满足客户,需要不断的增加其他车型的产线。在扩充的过程中,不仅工厂面积要扩宽、对应的设备也要增加。所以工厂变得很混乱,做什么事请的人都有,非常不便于生产管理。由于工厂是封闭的,客户并不知道工厂可以生产什么车型,于是凭以往的经验提供材料订车。有些客户就悲剧了,提供了材料,一段时间后才发现工厂给不了这样的车子。很浪费客户的时间和精力。经过上面的教训,聪明的同学就把一个工厂只负责一种车型,然后弄了一个园区,里面新建几个不同的工厂,需要增加车型再新建工厂。并且在客户提需求的时候就会告诉他是否可以生产这样的车型。这样的优化,不仅生产管理不受影响,并且节省了客户订车的精力和时间。
对上面故事的分析:
例子1指的是没有使用工厂方法,我们需要在主程序中一步一步去实现创建对象的过程。代码结构复杂不清晰,不利于后续维护和扩展。
例子2指的是使用简单工厂,我们只需要调用统一接口并且传一个参数,就能得到我们需要的实例。这个已经满足方便的获得实例的需求,但是当产品类扩展的时候,我们需要改动工厂类。扩展的时候修改已有代码是危险的,你不能保证会对原有逻辑造成危害,所以我们需要重新测试这个部分的功能,于是又增加了测试的成本。
例子3指的是使用工厂方法,他是对简单工程的优化。我们通过调用不同的工厂类就能得到我们需要的实例。在后续需要扩展产品类的时候,只需要增加产品类和对应的工厂类就能完成功能。不会修改原有代码,扩展性很好。
1.3 类图
1.3.1 定义解释
FactoryMethod定义了创建Car的接口,让子类RedCarFactory和GreenCarFactory决定实例化哪一个Car。
1.3.2 参与者
Product(Car): 定义工厂方法所创建的对象。
ConcreteProduct(GreenCar,RedCar):对象的实例。
Creator(Factorymethod):申明工厂方法,返回一个对象。
ConcreteCreator(GreenCarFactory,RedCarFactory):实现工厂方法,返回对象的实例。
1.4 代码
1.4.1 工厂方法实现
定义一个Car的对象,通过颜色区分不同的Car。
public class Car {
private String mColor;
public Car(String pColor) {
mColor = pColor;
}
public void printColor() {
System.out.println("My color is "+ mColor);
}
}
定义GreenCar作为Car的实例。
public class GreenCar extends Car {
public GreenCar(String pColor){
super(pColor);
}
}
定义RedCar作为Car的实例。
public class RedCar extends Car {
public RedCar(String pColor) {
super(pColor);
}
}
定义一个接口作为工厂方法,返回Car对象。
public interface FactoryMethod {
Car produceCar();
}
实现工厂方法的接口,返回Car的实例RedCar。
public class RedCarFactory implements FactoryMethod{
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public Car produceCar() {
<span style="white-space:pre"> </span>return new RedCar("red");
<span style="white-space:pre"> </span>}
}
实现工厂方法的接口,返回Car的实例GreenCar。
public class GreenCarFactory implements FactoryMethod {
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public Car produceCar() {
<span style="white-space:pre"> </span>return new GreenCar("green");
<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>
}
测试以上的代码。
public class FactoryMethodTest {
public static void main(String[] args) {
FactoryMethodred CarFactory = new RedCarFactory();
Carca1 = redCarFactory.produceCar();
ca1.printColor();
FactoryMethod greenFactory = new GreenCarFactory();
Carcar2 = greenFactory.produceCar();
car2.printColor();
}
}
1.4.2 简单工厂
上面的对象类和实例类可以继续使用。
实现一个工厂类,里面包含创建不同实例的逻辑。
public classSimpleFactory {
private static final String RED = "red";
private static final String GREEN = "green";
public Car produceCar(StringpColor) {
if (RED.equals(pColor)) {
return new RedCar(pColor);
}elseif(GREEN.equals(pColor)){
return new GreenCar(pColor);
}else{
System.out.println("Please input correct color.");
return null;
}
}
}
测试以上的代码。
public classSimpleFactoryTest {
public static void main(String[] args){
SimpleFactorysimpleFactory = newSimpleFactory();
Carcar1 = simpleFactory.produceCar("red");
car1.printColor();
Carcar2 = simpleFactory.produceCar("green");
car2.printColor();
// Compile error below, factory can not produce blue car.
Carcar3 = simpleFactory.produceCar("blue");
car3.printColor();
}
}
1.5 特点
1. 从代码结构上看,代码结构清晰。
2. 从扩展性来看,使用工厂方法,实体类的增加不会修改原来的代码逻辑。
1.6 其他
1.6.1 代码下载地址
https://github.com/bird7310/DesignPatternExample.git
1.6.2 备注
1. 有些内容放到后面章节去说明,比如工厂方法与抽象工厂的区别。
2. 有些内容本文不会去介绍,比如《Effective Java》中推荐的静态工厂方法,比如工厂方法的优化等。
3. 工厂方法是一个思想,每个人理解会有一些不一样,只要能表现这样的思想就可以成为工厂方法。
4. 类图是上网找的一个eclipse的插件ModelGoon根据代码导出来的。不怎么好用,再去寻觅一个。
5. 多提意见,共同成长。