一、设计模式简介
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
二、设计模式的分类
设计模式主要可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。
创建型模式包括:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式包括:适配器模式、桥接模式、过滤器模式、组合模式、装饰器模式、外观模式、享元模式和代理模式。
行为型模式包括:责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、空对象模式、策略模式、模板模式和访问者模式。
三、工厂模式
本文主要介绍工厂模式,工厂模式是java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的好的方式。工厂模式主要有三类:
1)简单工厂模式
2)工厂方法模式
3)抽象工厂模式
这三种工厂模式逐步抽象,适用范围越来越广泛。
四、简单工厂模式
简单工厂模式是最原始的工厂模式,又称为静态工厂方法模式。它主要由三种角色组成:
1)工厂类:这是这种设计模式的核心,具体的产品由工厂生产出来,在java中通常是一个具体的类。
2)抽象产品:一般是一个抽象类或者接口,主要规定该类的功能和接口。
3)具体产品类:这个类要么是抽象产品的子类,要么调用了抽象产品的接口,总之是实现了抽象产品的功能。
接下来看一个具体的例子:
/** * 抽象产品 * @author Administrator * */ public interface Car { public void drive(); } /** * 具体产品类 * @author Administrator * */ public class benzCar implements Car { @Override public void drive() { System.out.println("驾驶奔驰车......"); } } /** * 具体产品类 * @author Administrator * */ public class bmwCar implements Car { @Override public void drive() { System.out.println("驾驶宝马车......"); } } /** * 工厂类 * @author Administrator * */ public class driverFactory { //返回类型必须为抽象产品角色 public static Car dirveCar(String params) throws Exception{ //判断逻辑,返回具体的产品角色给Client if(params.equals("benzCar")){ return new benzCar(); }else if(params.equals("bmwCar")){ return new bmwCar(); }else{ throw new Exception(); } } } //客户 public class Client { public static void main(String[] args) throws Exception { //告诉司机(工厂) 开奔驰车 Car car=driverFactory.dirveCar("benzCar"); //下命令开车 car.drive(); } }
通过这个例子,我们可以更好的理解什么是简单工厂模式,在这种模式下,我们可以根据客户的需求自由的创建对象进行服务。
五、工厂方法模式
工厂方法模式相比简单工厂模式进了一步,工厂类不再是一个静态方法,这个工厂类也可以被子类继承和改变,进而实现更加复杂的功能。所以在这种设计模式下,工厂类分化成了两个类,一个抽象工厂,一个是具体工厂。抽象工厂是工厂方法的核心,但是与应用程序无关,具体工厂反之,具体工厂含有大量的具体实现的细节,由应用程序调用实现具体的功能。下面继续是这个例子:
/** * 抽象产品 * @author Administrator * */ abstract class Car { abstract void drive(); } /** * 具体产品类 * @author Administrator * */ public class bmwCar extends Car { @Override public void drive() { System.out.println("驾驶宝马车......"); } } /** * 具体产品类 * @author Administrator * */ public class benzCar extends Car { @Override public void drive() { System.out.println("驾驶奔驰车......"); } } /** * 抽象工厂 用來生产车 * @author Administrator * */ public interface abstractFactory { public Car driveFactory(); } /** * 具体工厂 * 创建奔驰车对象 */ public class benzCarFactory implements abstractFactory { @Override public Car driveFactory() { return new benzCar(); } } /** * 具体工厂 * 创建宝马车对象 */ public class bmwCarFactory implements abstractFactory { @Override public Car driveFactory() { return new bmwCar(); } } //客户 public class Client { private static Car benzcar,bmwcar; private static abstractFactory benzcarfactory,bmwcarfactory; public static void main(String[] args) throws Exception { //告诉(工厂) 要奔驰车 benzcarfactory=new benzCarFactory(); benzcar=benzcarfactory.driveFactory(); //可以开车了 benzcar.drive(); System.out.println("-------------------"); bmwcarfactory=new bmwCarFactory(); bmwcar=bmwcarfactory.driveFactory(); bmwcar.drive(); } }
在上述的代码中可以看到改变,通过这种方式我们降低了代码之间的耦合度,使用不同的类实现了不同的功能,而且合理的使用了继承机制。这样还可以使结构边得更加的灵活,当有新的产品时,不需要去改变工厂类,只需要加上一个具体实现的继承类,就可以被使用了。大大的增加了代码的可维护性能。但是同时我们也看到,随着产品种类的增多,会出现大量与之对应的工厂类,这也将无形中增加我们的编码量。因此这种方法还有优化的空间。
六、抽象工厂模式
在抽象工厂中引出了产品族的概念,将众多的产品划分成产品族,比如跑车族,商务车族......通过产品族减少具体工厂的数量,使每一个具体工厂可以获得多种产品,减少了大量的代码量。
// 抽象工厂类 定义不同的产品之间的标准,商务车 public interface ICarA { public void drive(); } // 抽象工厂类 定义不同的产品之间的标准 跑车族 public interface ICarB { public void drive(); } //具体产品类 public class productAHongqi implements ICarA { @Override public void drive() { System.out.println("开商务族--红旗车"); } } //具体产品类 public class productABmw implements ICarA { @Override public void drive() { System.out.println("开商务族--宝马车 ..."); } } //具体产品类 public class producSporttBAudi implements ICarB { @Override public void drive() { System.out.println("开跑车族--奥迪车..."); } } //具体产品类 public class productSportBBenz implements ICarB { @Override public void drive() { System.out.println("开跑车族--奔驰车 ..."); } } /** * 抽象工厂类 创建跑车族跑车 * @author Administrator * */ public abstract class abstractoryFactory1 { abstract ICarB getProductBBenz(); abstract ICarB getProductBAudi(); } /** * 抽象工厂类 创建商务族跑车 * @author Administrator * */ public abstract class abstractoryFactory2 { abstract ICarA getProductABmw(); abstract ICarA getProductBHongqi(); } /** * 具体工厂类 跑车族 * @author Administrator * */ public class Factory1 extends abstractoryFactory1 { @Override ICarB getProductBBenz() { return new productSportBBenz(); } @Override ICarB getProductBAudi() { return new producSporttBAudi(); } } /** * 具体工厂类 * 商务族 * @author Administrator * */ public class Factory2 extends abstractoryFactory2 { @Override ICarA getProductABmw() { return new productABmw(); } @Override ICarA getProductBHongqi() { return new productAHongqi(); } } public class Client { public static void main(String[] args) { //工厂一制造的产品族车 abstractoryFactory1 factory1 = new Factory1(); ICarB productsportAbenz = factory1.getProductBBenz(); ICarB productsportBaudi = factory1.getProductBAudi(); productsportAbenz.drive(); productsportBaudi.drive(); //工厂二制造的产品族车 abstractoryFactory2 factory2 = new Factory2(); ICarA productAbmw = factory2.getProductABmw(); ICarA productBhongqi = factory2.getProductBHongqi(); productAbmw.drive(); productBhongqi.drive(); } }
最后总结一下,从工厂模式到抽象工厂模式,模式越来越复杂,但是可维护性能却越来越高,普适性越来越强。但是回归最初的目的,我们创造这一系列的设计模式是为了解耦,使业务逻辑更加容易理解,更好的被表达。在使用时我们需要具体问题具体分析,不能一概而论的使用某一种方法。