设计模式(Design patterns)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性(From百度百科)。一个设计模式是针对某一类问题的解决方案,而且已经成功的应用于许多的设计中。设计模式分为三种类型,共23种。
创建型模式:单例模式、抽象工厂模式、建造者模式、工厂方法模式、原型模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。今天简单介绍下工厂方法模式。
工厂方法模式定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法让一个类的实例化延迟到其子类。它属于创建型模式。
得到一个类的子类实例,最常用的方法是使用new关键字调用子类的构造方法,但是为了不让代码的耦合性太高或者用户不知道该类有哪些子类,这种情况下就可以使用工程方法模式来设计系统。
工厂方法模式的结构中包括四种角色,分别是抽象产品,具体产品,抽象工厂,具体工厂。抽象产品角色由抽象类(或者接口)担任,负责定义具体产品必须拥有的行为。具体产品是一个非抽象类,它是抽象产品的子类(或者实现类)。创建者是一个抽象类(或者接口),负责定义工厂类。具体创建者是抽象创建者的非抽象子类(或者实现类)。工厂方法模式的UML图如下。注:图片来自百度百科。
现在假设有如下场景。一个工厂,负责生产铅笔(pencil)、圆珠笔(ballpen)、签字笔(signpen)。定义抽象产品(笔)的接口Pen,具体产品Pencil(铅笔)、Ballpen(圆珠笔)、Signpen(签字笔);定义工厂类PenFactory。简单工厂方法模式的代码实现如下。
产品接口:
/** * 笔类的接口 * @author Vencoln * */ public interface Pen { /** * 书写 * @param mesage */ public abstract void write(String msg); } |
具体产品类:
/** * 铅笔类 * @author Vencoln * */ public class Pencil implements Pen { /** * 打印出msg的信息 */ @Override public void write(String msg) { System.out.println("铅笔书写内容:" + msg); } } /** * 圆珠笔 * @author Vencoln * */ public class Ballpen implements Pen { @Override public void write(String msg) { System.out.println("圆珠笔书写内容:" + msg); } } /** * 签字笔 * @author Vencoln * */ public class Signpen implements Pen { @Override public void write(String msg) { System.out.println("签字笔书写内容:" + msg); } } |
工厂类:
/** * 工厂类 * @author Vencoln * */ public class PenFactory { /** * 生产产品 * @param type * @return */ public Pen produce(String type){ if(type.equals("pencil")){ //实例铅笔 return new Pencil(); } else if(type.equals("ballpen")){ return new Ballpen(); } else if (type.equals("signpen")){ return new Signpen(); } else { System.out.println("您输入的产品类型不存在"); return null; } } } |
用户:
public class User { /** * @param args */ public static void main(String[] args) { PenFactory pf = new PenFactory(); Pen p = pf.produce("pencil"); p.write("你猜我是一只什么笔?"); p = pf.produce("ballpen"); p.write("你猜我是一只什么笔?"); p = pf.produce("signpen"); p.write("你猜我是一只什么笔?"); p = pf.produce("abc"); p.write("你猜我是一只什么笔?"); } } |
简单工厂方法模式中,工厂根据用户提供的实体类型来生产相应的产品,如果用户提供的产品类型错误,则会导致生产产品失败。下面我们来对简单工厂模式进行优化,抽象产品和具体产品类保持不变,优化工厂代码,结果如下:
/** * 生产圆珠笔 * @return */ public Pen proBallpen(){ return new Ballpen(); } /** * 生产铅笔 * @return */ public Pen proPencil(){ return new Pencil(); } /** * 生产签字笔 * @return */ public Pen proSignpen(){ return new Signpen(); } |
优化后的工厂类为每一种产品提供了一个生产的方法,用户需要什么产品就调用对应的方法即可,这样可以避免用户提供产品类型错误导致的问题。当添加了新品种的笔时,我们给工厂添加一个相应的方法即可。但是,在用户使用工厂之前,必须先把工厂实例化,这样显得有些麻烦。在此我们进一步优化工厂,把生成产品的方法都修饰为静态的。优化后用户生成产品的方式如下:
public class User { /** * @param args */ public static void main(String[] args) { Pen p = PenFactory.proPencil(); p.write("我是铅笔,不是圆珠笔"); } } |
以上三种工厂方法模式,在开发中一般使用的是静态工厂模式(第三种),它没有第一种的缺陷,同时它比第二种工厂方法模式使用方便。在产品关系设计中,用户使用产品只依赖于抽象,而没有依赖具体,这也是设计模式基本原则之一。
这样创新的模式,值得你的选择!
蜗牛学院,只为成就更好的你!
还在等什么,赶快关注蜗牛学院官方微信,加入到蜗牛学院的大家庭中来吧!