在我的公众号中,关于七种结构型设计模式已经全部讲完了:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。而十一种行为型模式我们说了4种:策略模式、模板方法模式、观察者模式、责任链模式。关于创建型设计模式我们还没有聊过,所以今天我们来聊一聊创建型模式,创建型模式一共有五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。今天我们先回顾一下工厂方法模式和抽象工厂模式。
先了解一些简单的概念:
工厂方法模式(Factory Pattern)中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
那么首先我们来看工厂方法模式:
概念上说创建对象时不会对客户端暴露创建的逻辑,这样的好处很明显,你不暴漏创建的逻辑,客户端就不用去关心你的创建逻辑了,就可以直接调用了,同时扩展性也高(为什么扩展性高我们待会看)。其实工厂方法模式就好像小商店和大广场的感觉一样,如果你住在郊区:你买菜要去菜市场,你买零食要去小商店,反正你要去很多地方,但是如果你住在购物广场旁边那就不一样了,买啥都去这里面溜达一下,大多数都能找到。所以说如果没有工厂方法模式,你创建对象首先要知道这个对象是干嘛的,不然就好像去菜市场买家具一样,但是有了工厂方法模式,你只需要知道你要创建哪一类对象就可以了。
那如何来实现一个工厂方法模式呢?既然是工厂,那首先这个工厂里面要有一些东西,这些东西肯定就是对象了,而且这些对象都有一个公共的接口(概念上说通过共同的接口只想新创建的对象)。所以我们要先定义一个公共的接口:
代码语言:javascript复制interface TopInter{
代码语言:javascript复制 void Common();
}
代码语言:javascript复制 有了接口我们再去搞几个对象出来:
代码语言:javascript复制
class C1 implements TopInter{
@Override
public void Common() {
System.out.println("我是类1");
}
}
class C2 implements TopInter{
@Override
public void Common() {
System.out.println("我是类2");
}
}
有了公共的接口,有了对象,那工厂就该出来了吧。
代码语言:javascript复制class FactoryTop {
public TopInter getShape(String type) {
if (type == null) {
return null;
}
if (type.equalsIgnoreCase("家具")) {
return new C1();
} else if (type.equalsIgnoreCase("零食")) {
return new C2();
}
return null;
}
}
看懂了吗?有了工厂方法模式,我们每次建了新的类之后,只需要在这个方法中加入一个判断返回新的实例就可以了,而不用像以往一样,自己挨个的创建类,还有可能创建错误。这就是我们开始所说容易扩展。
抽象工厂模式:
抽象工厂模式,名字和工厂方法模式很像,都和工厂有关,那么他们有什么区别呢?抽象工厂模式,是对工厂进行抽象,也就是说
他是创建工厂的的工厂。就好比一个总部的酒厂下面有很多分部的酒厂,这些分部的酒厂创建不同型号的酒。这个就是抽象工厂模式。概念上来说:
工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。 抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承。
如果我描述的还是很晦涩,那么我希望下面这个例子能帮到你:
在上面我们创建了一个TopInter的接口,他的下面有两个类分别是C1和C2。现在我们再创建一个接口SecInter和他的两个实现类S1和S2
代码语言:javascript复制interface SecInter{
void write();
}
class S1 implements SecInter{
@Override
public void write() {
System.out.println("我是S1");
}
}
class S2 implements SecInter{
@Override
public void write() {
System.out.println("我是S2");
}
}
然后我们来写抽象工厂类:
代码语言:javascript复制abstract class FactoryTop {
abstract TopInter getTop();
abstract SecInter getSec();
}
既然抽象工厂是创建工厂的工厂,那么实现这个抽象类的类肯定也是工厂,只不过这些工厂所做的事情有所区别:
代码语言:javascript复制
class Top extends FactoryTop{
@Override
TopInter getTop(String s) {
if (s=="家具"){
return new C1();
}else {
return new C2();
}
}
@Override
SecInter getSec(String s) {
return null;
}
}
class Sec extends FactoryTop{
@Override
TopInter getTop(String s) {
return null;
}
@Override
SecInter getSec(String s) {
if (s=="82年拉菲"){
return new S1();
}else {
return new S2();
}
}
}
抽象工厂类有了,工厂类也有了,那么我们怎么去获取工厂呢?这就需要我们提供一个生产商,让他们给你生产出来你想要的工厂:
代码语言:javascript复制public class FactoryProducer {
public static FactoryTop getFactory(String choice){
if(choice.equalsIgnoreCase("top")){
return new Top();
} else if(choice.equalsIgnoreCase("sec")){
return new Sec();
}
return null;
}
}