设计模式 | 飞机票 |
---|---|
三大工厂模式 | 登机入口 |
策略模式 | 登机入口 |
委派模式 | 登机入口 |
模板方法模式 | 登机入口 |
观察者模式 | 登机入口 |
单例模式 | 登机入口 |
原型模式 | 登机入口 |
代理模式 | 登机入口 |
装饰者模式 | 登机入口 |
适配器模式 | 登机入口 |
建造者模式 | 登机入口 |
责任链模式 | 登机入口 |
享元模式 | 登机入口 |
组合模式 | 登机入口 |
门面模式 | 登机入口 |
桥接模式 | 登机入口 |
中介者模式 | 登机入口 |
迭代器模式 | 登机入口 |
状态模式 | 登机入口 |
解释器模式 | 登机入口 |
备忘录模式 | 登机入口 |
命令模式 | 登机入口 |
访问者模式 | 登机入口 |
软件设计7大原则和设计模式总结 | 登机入口 |
设计模式系列文章将会介绍全部的GoF23种设计模式,希望能和大家一起交流学习。
本文会介绍工厂模式的三种写法
指的是由一个工厂对象来决定创建具体的产品实例,简单工厂模式并不属于GoF23种设计模式之一,但是我们在平常开发中也运用的非常广泛。
创建一个产品接口:
package com.zwx.design.pattern.factory.simple;
public interface IProduct {
void grow();
}
创建产品苹果类:
package com.zwx.design.pattern.factory.simple;
public class Apple implements IProduct {
@Override
public void grow() {
System.out.println("种植苹果");
}
}
创建产品桔子类:
package com.zwx.design.pattern.factory.simple;
public class Orange implements IProduct {
@Override
public void grow() {
System.out.println("种植桔子");
}
}
创建一个简单工厂类,里面封装了创建具体产品对象的方法
package com.zwx.design.pattern.factory.simple;
public class SimpleFactory {
public IProduct createProduct(String productType){
if("apple".equals(productType)){
return new Apple();
}else if("orange".equals(productType)){
return new Orange();
}
return null;
}
}
最后让我们来新建一个测试类测试一下
package com.zwx.design.pattern.factory.simple;
public class TestSimpleFactory {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
IProduct apple = factory.createProduct("apple");
apple.grow();//输出:种植苹果
IProduct orange = factory.createProduct("orange");
orange.grow();//输出:种植桔子
}
}
上面就基本上实现了一个简单工厂模式,但是我们发现,假如我们要增加一个产品西瓜,那么我们就需要去修改创建工厂实现了类,这就违背了软件设计的开闭原则,所以,我们可以对SimpleFactory类利用反射进行改进。
改进后的工厂实现类,新增了一个createProduct2方法
package com.zwx.design.pattern.factory.simple;
public class SimpleFactory {
public IProduct createProduct(String productType){
if("apple".equals(productType)){
return new Apple();
}else if("orange".equals(productType)){
return new Orange();
}
return null;
}
public IProduct createProduct2(Class<? extends IProduct> clazz) throws Exception {
if (null == clazz){
throw new Exception("无法识别的产品");
}
return clazz.newInstance();
}
}
测试类:
package com.zwx.design.pattern.factory.simple;
public class TestSimpleFactory {
public static void main(String[] args) throws Exception {
SimpleFactory factory = new SimpleFactory();
IProduct apple = factory.createProduct2(Apple.class);
apple.grow();//输出:种植苹果
IProduct orange = factory.createProduct2(Orange.class);
orange.grow();//输出:种植桔子
}
}
可以看到,这种写法解决了可能存在的if分支过多造成工厂类臃肿的问题,但是这种方法真的完美吗?请继续往下看。。。
简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心
假如每种产品创建不仅仅只是实例化一个对象,还有其他逻辑需要处理,那么我们无法直接使用一句反射,避免不了写很多if(亦或者用switch循环),这样的话每新增一个产品我们都需要修改工厂实现类,随着产品链越来越丰富,工厂的职责会变得越来越多,久而久之会越来越难以维护。
工厂方法模式是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个对象,工厂方法让类的实例化推迟到子类中进行,在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。
新建一个产品接口
package com.zwx.design.pattern.factory.method;
public interface IProduct {
void grow();
}
新建一个具体产品苹果类
package com.zwx.design.pattern.factory.method;
public class Apple implements IProduct {
@Override
public void grow() {
System.out.println("种植苹果");
}
}
新建一个具体产品桔子类
package com.zwx.design.pattern.factory.method;
public class Orange implements IProduct {
@Override
public void grow() {
System.out.println("种植桔子");
}
}
现在我们需要将工厂也抽象化:
新建一个工厂接口,定义一个create方法,这个方法的返回值就是产品
package com.zwx.design.pattern.factory.method;
public interface IFarmFactory {
IProduct create();
}
新建一个生产苹果的具体工厂类,并实现工厂接口IFarmFactory
package com.zwx.design.pattern.factory.method;
public class AppleFactory implements IFarmFactory {
@Override
public IProduct create() {
return new Apple();
}
}
新建一个生产桔子的具体工厂类,并实现工厂接口IFarmFactory
package com.zwx.design.pattern.factory.method;
public class OrangeFactory implements IFarmFactory {
@Override
public IProduct create() {
return new Orange();
}
}
最后,添加测试类
package com.zwx.design.pattern.factory.method;
public class TestFactoryMethod {
public static void main(String[] args) {
IFarmFactory appleFactory = new AppleFactory();
IProduct apple = appleFactory.create();
apple.grow();//输出:种植苹果
IFarmFactory orangeFactory = new OrangeFactory();
IProduct orange = orangeFactory.create();
orange.grow();//输出:种植桔子
}
}
这时候如果需要新增其他商品,需要创建两个类:一个具体产品类,一个具体工厂类。
看完这个例子家应该很明白工厂方法和简单工厂的区别了,简单工厂就是所有产品都由一个工厂类一个方法来创建,而工厂方法将工厂的职责也进行细化了,每种产品都由自己特定的工厂来生产,这也是单一职责原则的体现。
1、创建对象需要大量重复的代码。
2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
3、一个类通过其子类来指定创建哪个对象。
1、类的个数容易过多,增加复杂度。
2、增加了系统的抽象性和理解难度
抽象工厂模式是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
新建一个苹果的接口,定义一个种植苹果的方法
package com.zwx.design.pattern.factory.abstractMethod;
public interface IApple {
void growApple();
}
新建一个具体产品南方苹果类来实现IApple接口
package com.zwx.design.pattern.factory.abstractMethod;
public class SouthApple implements IApple {
@Override
public void growApple() {
System.out.println("种植南方苹果");
}
}
新建一个桔子的接口,定义一个种植桔子的方法
package com.zwx.design.pattern.factory.abstractMethod;
public interface IOrange {
void growOrange();
}
新建一个具体产品南方桔子类来实现IOrange接口
package com.zwx.design.pattern.factory.abstractMethod;
public class SouthOrange implements IOrange {
@Override
public void growOrange() {
System.out.println("种植南方桔子");
}
}
以上就是一个将产品抽象化的过程,接下来我们就需要将产品交给工厂进行创建。
新建一个抽象工厂接口,定义两个方法:一个用来创建苹果对象,一个用来创建桔子对象
package com.zwx.design.pattern.factory.abstractMethod;
public interface IFactory {
IApple createApple();
IOrange createOrange();
}
新建一个具体工厂南方工厂类来实现IFactory接口,并实现其中的两个抽象方法
package com.zwx.design.pattern.factory.abstractMethod;
import com.zwx.design.pattern.factory.method.IProduct;
public class SouthFarmFactory implements IFactory {
@Override
public IApple createApple() {
return new SouthApple();
}
@Override
public IOrange createOrange() {
return new SouthOrange();
}
}
最后我们来测试一下
package com.zwx.design.pattern.factory.abstractMethod;
public class TestAbstractFactory {
public static void main(String[] args) {
IFactory southFarmFactory = new SouthFarmFactory();
IApple apple = southFarmFactory.createApple();
apple.growApple();//输出:种植南方苹果
IOrange orange = southFarmFactory.createOrange();
orange.growOrange();//输出:种植南方桔子
}
}
假如说这时候又有一个新的农场要建立生产一样的产品,那么就可以再新建一个对应的产品类和对应的工厂类就可以实现了。
当我们有一系列产品(如上面的Apple,Orange)。而这一系列产品每种产品又需要具有不同的创建方法(如上种植Apple和种植Orange方法肯定是不同的需要不同的方法实现)。
1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂
的接口。
2、增加了系统的抽象性和理解难度。
本文主要介绍了三种工厂模式的实现,其中简单工厂模式并不属于GoF23中设计模式之一。并且针对每种工厂模式给出了对比和代码示例帮助理解,每种工厂模式都适用于不同的业务场景,实际开发过程中可以根据需要进行选择。