这三种设计模式是层层演进的关系,所以就搁在一起来进行理解。
大多数的设计模式都可以根据其名字来进行猜测作用,它们都是工厂模式,先在脑海里转一转现实生活中的工厂是做什么的。工厂嘛,就是用来生产产品用的,每个产品都有一些特定的功能,想到这里,是不是跟代码中的类很像了,类都是具有一定职责的(或者叫功能),生产产品就是创建具有某种功能的类的实例。
假定有产品A,B,C分别对应于class ProductA,class ProductB,class ProductC.
情形一:不使用任何的模式,只是由使用者来创建各种实例,代码就是这样了
ProductA productA = new ProductA();
ProductB productB = new ProductB();
ProductC productC = new ProductC();
缺点:看看这种写法,具体的使用者就扮演了全知全能的角色,使用者要知道每个类的构造,如果产品又有了D ,E ,F ...想想都觉得很麻烦。
最好能有一种办法来进行简化。如果这A,B,C所做的事没有任何的联系,那么改善代码的办法暂时不好做。
情形二:如果A,B,C的职责有共通性,比如说,A做加法的,B做减法的,C做除法的,虽然各不相同,但是都算是运算的一种的,大家都是输入参数,得到结果。这个时候可以有一个抽象了,叫class Product能输入参数得到结果。
同时假设符号A代表ProducA,符号B代表ProducB,符号C代码ProductC,这样使用者使用如下(代码只是用于示意,不用在意具体写法):
Class Product{
setParams(a,b)
getResult()
}
Class ProductA extend Product{
setParams(a,b)
getResult()
}
Class ProductB extend Product{
setParams(a,b)
getResult()
}
Class ProductC extend Product{
setParams(a,b)
getResult()
}
Class Factory{
Product createProduct(param){
switch(param){
case:‘A’
return new ProductA();
break;
case: 'B'
return new ProductB();
break;
case: ‘C’
return new ProductC();
break;
}
}
}
//客户端进行使用的时候,需要这样做
Factory factory = new Factory();
Product concreteProduct = factory.createProduct('A');
concreteProduct.setParams(1,2);
concreteProduct.getResult();
优点:如果需要拓展类似的操作就只用一个新类进行继承就好了,同时客户端只需要认识抽象的Product和工厂就好,简化了使用和拓展。
缺点:1.虽然使用者不用扮演全能全知的角色了,但是工厂类就扮演了这个角色
2.如果需要进行新的产品加入,就需要改动工厂类,就是在分支判断语句中进行添加。这违法了对拓展开放,对修改关闭的原则(设计模式原则之一)。
其相应的类图如下:
到目前为止,改进算是成功,使用也可以使用可以,这个模式就叫做简单工厂模式。
情形三:如果需要改进,将其破坏了设计模式原则部分的给改过来。简单工厂模式体现一个具体的工厂可以生成一个抽象产品,如果改成一个具体的工厂只生成一个具体产品,一个抽象的工厂生成一个抽象产品,具体对具体,抽象对抽象,那么问题就解决了。将设计变的更加的抽象,面向接口编程,其代码实现如下:
Class Product{
setParams(a,b)
getResult()
}
Class ProductA extend Product{
setParams(a,b)
getResult()
}
Class ProductB extend Product{
setParams(a,b)
getResult()
}
Class ProductC extend Product{
setParams(a,b)
getResult()
}
//使得工厂类变抽象类
Class Factory{
Product createProduct(param)
}
Class FactoryA{
ProductA createProduct(param)
}
Class FactoryB{
ProductB createProduct(param)
}
Class FactoryC{
ProductC createProduct(param)
}
//客户端进行使用的时候,需要这样做
Factory concreteFactory = new FactoryA();
Product concreteProduct = concreteFactory.createProduct();
concreteProduct.setParams(1,2);
concreteProduct.getResult();
优点:观察一下客户端的使用,客户端调用的时候只需要关心抽象工厂和抽象产品中的方法即可,根据自己的使用来获取工厂。这样就修复了简单工厂模式对设计原则的破坏。
缺点:更多的类文件。(这个也是很烦人的,实际项目中也不愿意多一些类文件,具体的抉择看使用者的需求了。)
这个改进后的模式就是工厂模式。
给出其类图如下:
情形四:简单工厂模式本身就有违法开放-封闭原则,工厂模式才是算是一个真正意义上合格的设计模式。工厂模式主要是任务是产生一系列产品,产品只有一个系列。如果一个工厂需要能够产生多个系列的产品呢?按照正常的思维去想,工厂模式中的抽象工厂只含有一个createProduct()函数,返回的是一个Product类,这个类代表着某一系列的产品,如果再添加一个createBigProduct()函数来创建一个BigProduct类,产品BigProduct可以与产品Product所做的事情完全不一样,是不是就可以多了一个系列的呢?这样的想法完全具有可行性,给出具体的代码:
Class Product{
setParams(a,b)
getResult()
}
Class ProductA extend Product{
setParams(a,b)
getResult()
}
Class ProductB extend Product{
setParams(a,b)
getResult()
}
Class BigProduct{
getBigResult();
}
class BigProductA extend BigProduct{
getBigResult();
}
class BigProductB extend BigProduct{
getBigResult();
}
//使得工厂类变抽象类
Class Factory{
Product createProduct()
BigProduct createBigProduct()
}
Class Factory1{
ProductA createProduct()
BigProductA createBigProduct()
}
Class Factory2{
ProductB createProduct()
BigProductB createBigProduct()
}
//客户端进行使用的时候,需要这样做
//使用者,只需要认识一个抽象工厂Factory,几种抽象产品,就可以很愉快的使用了,只要找到不同的工厂
Factory factory = new Factory1();
Product concreteProduct = factory.createProduct();
BigProduct concreteBigFactory = factory.createBigProduct();
concreteProduct.setParams(1,2);
concreteProduct.getResult();
concreteBigFactory.getResult();
同样的观察下代码,使用者需要知道是抽象工厂,多种抽象产品,以及具体的工厂,这样子,如果你如何进行拓展,客户端的使用方法都不变,新业务的扩充对使用者的影响极小,是不是很棒。上面说到过,这种写法实现了多个系列的产品,其实完全可以叫复杂的工厂模式,为啥?因为抽象工厂职责变多了,由生产一个抽象产品,变成了生产多个抽象产品。复杂工厂模式有点low有木有,算了就叫 抽象工厂模式好了(作者意淫,不知道为啥去这个名字,可能真的是如此,哈哈)。类图的就省略了,任性orz!!!
OK ,让我们总结一下:
1.简单的工厂模式:只对产品做了抽象,一个抽象产品对应于一个系列的具体产品。在使用的过场中,将某个具体的产品类对应于某个字符,通过传递字符的方式来获得某个具体产品。这样做法很常用的,如果具体的产品类很稳定,这样做超级实用,因为需要创建类文件比较少。有点小瑕疵是并没有完全遵循设计模式,有新的产品加入,需要修改工厂类。
2.工厂模式:这个模式才是真正的工厂模式,符合设计模式,开始了面向对象或者接口编程,有一点点小小麻烦的是,一个具体的工厂对应一个具体的产品,每次要新增产品,工厂也要新增,创建的小类文件比较多。嗯哼,谁让你要好处的呢,总要点代价吧。这个模式是只有一个抽象产品,能生产一个系列的产品。
3.抽象工厂模式:能够生产多个系列的产品了,一个抽象的工厂类中有多个抽象出来的产品,每个抽象的产品代表一个系列的产品。具体的工厂类生产具体的产品,其实还隐含的兼职了组合的功能。如果有小系列产品中有m种具体的产品,大系列的产品有n种具体的产品,那么的具体工厂其实可以有m*n个。到这个模式为止,还是有毛病的,并不能完美的撒花完结。一个抽象工厂类是包含的抽象产品是有限的,如果再多一个抽象产品,就需要拓展。知道有这个毛病就好,暂时搁置。
最后附上地址(会逐渐在代码加入二十三种设计模式):https://github.com/ArronXiao/DesignPattern