什么是开闭原则:
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
所以简单工厂不属于设计模式内的,但是并不是说简单工厂是错误的,只是根据具体情况使用而已。
下面我就针对简单工厂、工厂方法、抽象工厂结合Demo演示给大家。
正文
如图,就是工厂模式的划分。
简单工厂
概念:一个工厂类根据传入的参量决定创建出那一种产品类的实例。
想象一下汽车生产厂生产汽车,有两个工厂,分别是宝马和奔驰,客户想要买这两种车,就要分别去这两个工厂去买,结合在代码里就是客户分别传递不同的参数才可以得到不同的对象。
首先我们需要一个接口, 用来返回不同品牌的汽车。
public interface Car { void produce(); }
然后我们需要两个汽车
public class Benz implements Car { public void produce() { System.out.println("生产一辆奔驰"); } } public class BMW implements Car { public void produce() { System.out.println("生产一辆宝马"); } }
接下来就是工厂,这个工厂就是根据客户传过来的不同参数返回不同的汽车。
public class CarFactory { public Car produce(String type) { if ("bmw".equals(type)) { return new BMW(); } else if ("benz".equals(type)) { return new Benz(); }else{ System.out.printIn("类型错误"); } return null; } }
最后来了一个顾客说是要买宝马,让我们来测试一下吧
public class SimpleFactoryTest { public static void main(StringD args) { CarFactory factory = new CarFactory(); Car car = factory.produce("bmw"); car.produce(); } }
大家看代码可以得知,现在是两个车,就要写两个if去判断,如果以后出现很多个产品我个么就就要在1工厂方法里写多个if,这样就会造成拓展业务需要修改原有代码来实现,这样的写法可以实现,但是很low,建议同学们尝试以下两种。
工厂方法模式
概念:定义一个创建对象的接口,让子类决定实例化那个类。
工厂模式细分的话有两种,我在代码里会讲解一种,另一种在示例代码中体现,被我注释掉的就是普通工厂方法,大家一看便知。
与简单工厂重复的代码我就贴在一个代码块中了。
public interface Car { void produce(); } public class Benz implements Car { public void produce() { System.out.println("生产一辆奔驰"); } } public class BMW implements Car { public void produce() { System.out.println("生产一辆宝马"); } }
不同的地方就是工厂的写法,我们一个汽车品牌就新建一个工厂 方法。
public class BenzCarFactory { /** *工厂方法 * @return */ // public Car produceBenz() { // return new Benz(); // } /** *静态工厂方法 * * @return */ public static Car produceBenz() [ return new Benz(); } } public class BMWCarFactory{ /** *工厂方法 *@return */ // public Car produceBMW(){ // return new BMW(); //} /** * 静态工厂方法 * @return */ public static Car produceBMW() { return new BMW(); } }
因为只静态的方法,那么在jvm加载时就已经创建了,所以我们在引|用的时候就不用new工厂对象了,这也是普通工厂方法与静态工厂方法的区别所在。
让我们看一下客户是怎么购买汽车的。
public class FactoryMethodTest { //psvm . public static void main(StringD args) { /** *工厂方法 */ //BenzCarFactory factory = new BenzCarFactory(); // Car car = factory.produceBenz(); // car.produce(); /** *静态工厂方法*/ Car car = BenzCarFactory.produceBenz(); car.produce(); } }
可以看出,每个工厂只生产一种产品,客户端通过不同的工厂去生产不同的产品。这样做的好处就是我们对业务进行拓展时不用更改代码,只需要新增一个拓展对产品或者对象就可以,这也是最简单也是我认为最常用对工厂方法了。
抽象工厂
概念:创建相关或依赖对象的家族, 而无需明确指定具体类。
抽象工厂适用于复杂业务需求,复杂的产品生产场景中。怎么复杂呢?就是产品属性多了一个纬度,之前我们都是生产汽车,但是现在要区分出生产的颜色,对汽车的要求不仅仅是品牌还有颜色了。
来看看具体的代码实现:
首先定义三种颜色的接口
public interface Black { void create(); } public interface Red { void create(); } public interface White { void create(); }
然后定义我们存在的产品,我们现在只有黑色奔驰,黑色宝马,白色奔驰,白色宝马,红色奥迪。分别创建这五个产品的类。
public class BenzBlack implements Black { public void create() { System.out.printIn("黑色奔驰"); } } public class BenzWhite implements White { public void create() { System.out.printIn("白色奔驰"); } } public class BMWBlack implements Black { public void create() { System.out.println("黑色宝马"); } } public class BMWWhite implements White { public void create() { System.out.printIn("白色宝马"); , } } public class RedAudi implements Red { public void create() { System.out.println("红色奥迪"); } }
然后我们定义工厂接口,工厂接口是把刚才颜色接口进行了统一整理在一 起。说明我们现在可以生产这三种颜色任意品牌汽车。
所以说对业务拓展性非常高。
public interface CarFactory { Black black(); White white(); Red red();
那么就让我们随意创建E种汽车的工厂。
public class AudiFactory implements CarFactory{ public Black black() { return null; } public White white(){ return null; } public Red red(){ return new RedAudi(); } public class BenzFactory implements CarFactory{ public Black black(){ return new BenzBlack(); } public White white(){ return new BenzWhite(); } public Red red() { return null; } } public class BMWFactory implements CarFactory { public Black black() { return new BMWBlack(); } public White white() { return new BMWWhite(); } public Red red() { return null; } }
让我们来测试一下:
public class AbstractFactoryMethodTest{ public static void main(StringD args){ AudiFactory audi = new AudiFactory(); Red redAudi = audi.red(); redAudi.create(); BenzFactory benz = new BenzFactory(); Black blackBenz = benz.black(); blackBenz.create(); } }
输出结果如下:
总结
简单工厂模式适用于工厂类需要创建的对象比较少的情况,客户只需要传入具体的参数,就可以忽略工厂的生产细节,去获取想要的对象;
工厂方法模式,主要是针对单一产品结构的情景,拓展时只需增加一个工厂类就可以;
抽象工厂模式则是针对多级产品结构(系列产品)的一种工厂模式,拓展时增加多个类,改动比较大;
最后在说一下, 每种模式都有自己的优点和弊端,没有最好的模式,只有最适合的模式,只要符合实际开发需求就是最好的。