工厂设计模式
一、简介
都不知道简介要写什么,工厂模式嘛,就是工厂嘛,生产东西的嘛……
在Java里面就是用来帮助我们生产对象的咯~~
主要作用嘛,大概就是将创建和使用对象拆分减低耦合度吧。
二、分类
分类的话,大致可以分成3种
- 简单工厂
- 工厂方法
- 抽象工厂
这里有一件比较有意思的是,简单工厂是不包含在gof23种设计模式里面的,据说是因为过于简单了,hhhh。
三、简单工厂
简单工厂模式算是3种工厂模式中最基础最简单的了,用的也是最多的。
简单工厂模式具体的思路是这样的:
提供一个抽象基类以及若干具体的子类,提供一个工厂和一个客户端
通常情况下根据需求创建对象的逻辑都是由客户端去完成的,这里客户端指的是创建和使用对象的类,因为不知道怎么叫就叫客户端吧
而工厂的作用就是使用一个工厂类将创建对象这一部分拆分出来交给工厂,客户端只负责从工厂拿到对象然后去使用对象的功能
工厂返回的对象也是抽象基类类型,具体实现是的什么子类是由工厂来决定的(动态绑定)
我们在想要使用简单工厂模式的时候,只需要分清楚三个角色:工厂、基类、子类就可以了
下面是简单工厂模式的类图
下面是代码示例,大概讲一下示例的流程背景
假设我们有一家饼干店类(用来卖饼干的),有若干个饼干类(饼干),每次卖饼干的时候都要根据条件创建不同的饼干类型,每次多出一个饼干类的时候我们都要修改饼干店的源代码,现在我们希望使用工厂模式来拆分饼干店的职责(你就负责卖,别的不需要你操心),将创建饼干对象(new 对象)的这一部分交给一个工厂来处理,工厂处理好后直接返回饼干(对象)供饼干店使用
那下面的代码就产生了:
/**
* @author ZhongJing </p>
* @Description 饼干抽象类 </p>
*/
public abstract class BaseBiscuits {
/**
* 描述饼干的制作过程
* 抽象方法,让具体的饼干子类来重写
*/
public abstract void makeBiscuits();
}
/**
* @author ZhongJing </p>
* @Description 曲奇饼干 </p>
*/
public class Cookies extends BaseBiscuits{
@Override
public void makeBiscuits() {
System.out.println("曲奇饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description 夹心饼干 </p>
*/
public class SandwichBiscuits extends BaseBiscuits {
@Override
public void makeBiscuits() {
System.out.println("夹心饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description 饼干工厂类 </p>
*/
public class BiscuitsFactory {
/**
* 静态方法,根据传入的饼干类型创建不同的饼干
* @param biscuitsType 饼干类型
* @return 饼干的具体对象
*/
public static BaseBiscuits createBiscuits(String biscuitsType) {
BaseBiscuits biscuits = null;
if ("cookies".equalsIgnoreCase(biscuitsType)) {
biscuits = new Cookies();
} else if ("sandwich".equalsIgnoreCase(biscuitsType)) {
biscuits = new SandwichBiscuits();
} else {
System.out.println("不存在该类型的饼干,类型:" + biscuitsType);
}
return biscuits;
}
}
/**
* @author ZhongJing </p>
* @Description 饼干店(客户端) </p>
*/
public class BiscuitsStore {
public static void main(String[] args) {
String type1 = "cookies";
String type2 = "sandwich";
BaseBiscuits biscuits = BiscuitsFactory.createBiscuits(type1);
biscuits.makeBiscuits();
BaseBiscuits biscuits2 = BiscuitsFactory.createBiscuits(type2);
biscuits2.makeBiscuits();
}
}
四、工厂方法
在了解了简单工厂以后,心里总会有一个疑问,把创建对象交给工厂对于调用的类来说确实是方便了,也降低了耦合度,也不用一直修改了,但是工厂和类之间的耦合度不是依旧很高嘛,而且如果每新增一个基类就要修改一次工厂的代码,依旧是一件很麻烦的事情,有没有一种办法,可以只新增而不修改旧的代码呢?
有,就是工厂方法。
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。
大概的类图就是下面这样的,和简单工厂基本一样,只不过创建对象由子类来完成了,基类工厂只提供方法.
这样做的好处就在于,不管产品的子类如何新增或者改变,都可以通过修改或者新增子类工厂的方式来解决问题。
当然,工厂方法也是有坏处的。
当我们的产品子类新增是,往往伴随着子类工厂的新增,如果持续下去就会发生类爆炸,增加系统的负荷。
所以也不是什么地方都可以使用的,工厂方法一般都适用于框架上游,在编写时我根本不知道到底会有什么子类,我只需要定义方法和返回的基类,具体的实现将会由整合的框架下游或者开发人员来实现,也算是一种规范的制定吧。
现在我们将之前的简单工厂修改一下,变成工厂方法,代码如下
/**
* @author ZhongJing </p>
* @Description 饼干抽象类 </p>
*/
public abstract class BaseBiscuits {
/**
* 描述饼干的制作过程
* 抽象方法,让具体的饼干子类来重写
*/
public abstract void makeBiscuits();
}
/**
* @author ZhongJing </p>
* @Description 曲奇饼干 </p>
*/
public class Cookies extends BaseBiscuits {
@Override
public void makeBiscuits() {
System.out.println("曲奇饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description 夹心饼干 </p>
*/
public class SandwichBiscuits extends BaseBiscuits {
@Override
public void makeBiscuits() {
System.out.println("夹心饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description 工厂基类 </p>
*/
public abstract class BaseBiscuitsFactory {
/**
* 只提供创建饼干对象的方法,具体创建哪种饼干由子类来决定
*/
public abstract BaseBiscuits createBiscuits();
}
/**
* @author ZhongJing </p>
* @Description 创建曲奇饼干的工厂 </p>
*/
public class CookiesFactory extends BaseBiscuitsFactory{
@Override
public BaseBiscuits createBiscuits() {
return new Cookies();
}
}
/**
* @author ZhongJing </p>
* @Description 创建夹心饼干的工厂 </p>
*/
public class SandwichBiscuitsFactory extends BaseBiscuitsFactory{
@Override
public BaseBiscuits createBiscuits() {
return new SandwichBiscuits();
}
}
/**
* @author ZhongJing </p>
* @Description 饼干店(客户端) </p>
*/
public class BiscuitsStore {
public static void main(String[] args) {
BaseBiscuits cookies = createBiscuits(new CookiesFactory());
cookies.makeBiscuits();
BaseBiscuits sandwichBiscuits = createBiscuits(new SandwichBiscuitsFactory());
sandwichBiscuits.makeBiscuits();
}
public static BaseBiscuits createBiscuits(BaseBiscuitsFactory factory) {
return factory.createBiscuits();
}
}
五、抽象工厂
概述:
抽象工厂提供一个接口以创建一系列相关或相互依赖的对象,而无需指定它们具体的类
抽象工厂目的其实就是根据不同的分类创造出一个对象族,在我看来简单工厂、工厂方法、抽象工厂就像是一个递推逐渐复杂化的过程,其实本质的原则都是一样的,只不过相对于工厂方法,抽象工厂不再是只创建一种对象,而是直接创建一个族群的对象而已。
抽象工厂的角色依旧分为抽象工厂、具体工厂、抽象产品、具体产品四种角色。
他的UML类图大概是这样的
现在我们来修改一下之前饼干店的例子,假设现在我们饼干店越做越大,开了一家分店,就叫分店B吧,我们同时拥有了两家店,用户也有了更多的选择,因为是连锁店,饼干的类型依旧是原来的类型但是口感存在着差异,有的客户喜欢吃A店的,而有的客户又喜欢吃B店的,这种情况下一个单一的工厂已经解决不了我们现存的问题了,就需要我们使用抽象工厂来进行分类,A店的所有饼干就相当于一个对象族、B店的所有饼干是另外一个对象族
下面通过代码来实现一下我们的需求:
/**
* @author ZhongJing </p>
* @Description 曲奇抽象类 </p>
*/
public abstract class BaseCookies {
/**
* 描述制作曲奇饼干的流程
*/
public abstract void makeCookies();
}
/**
* @author ZhongJing </p>
* @Description 夹心饼干抽象类 </p>
*/
public abstract class BaseSandwich {
/**
* 描述夹心饼干的制作过程
*/
public abstract void makeSandwich();
}
/**
* @author ZhongJing </p>
* @Description A店的曲奇饼干(具体类) </p>
*/
public class CookiesA extends BaseCookies{
@Override
public void makeCookies() {
System.out.println("A店曲奇饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description B店的曲奇饼干(具体类) </p>
*/
public class CookiesB extends BaseCookies{
@Override
public void makeCookies() {
System.out.println("B店曲奇饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description A店的夹心饼干(具体类) </p>
*/
public class SandwichA extends BaseSandwich{
@Override
public void makeSandwich() {
System.out.println("A店夹心饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description B店的夹心饼干(具体类) </p>
*/
public class SandwichB extends BaseSandwich {
@Override
public void makeSandwich() {
System.out.println("B店夹心饼干制作完成……");
}
}
/**
* @author ZhongJing </p>
* @Description 抽象工厂类 </p>
*/
public abstract class BaseBiscuitsFactory {
/**
* 制作曲奇饼干
*/
public abstract BaseCookies createCookies();
/**
* 制作夹心饼干
*/
public abstract BaseSandwich createSandwich();
}
/**
* @author ZhongJing </p>
* @Description A店工厂实现类 </p>
*/
public class BiscuitsFactoryA extends BaseBiscuitsFactory{
@Override
public BaseCookies createCookies() {
return new CookiesA();
}
@Override
public BaseSandwich createSandwich() {
return new SandwichA();
}
}
/**
* @author ZhongJing </p>
* @Description B店工厂实现类 </p>
*/
public class BiscuitsFactoryB extends BaseBiscuitsFactory {
@Override
public BaseCookies createCookies() {
return new CookiesB();
}
@Override
public BaseSandwich createSandwich() {
return new SandwichB();
}
}
/**
* @author ZhongJing </p>
* @Description 客户端 </p>
*/
public class Client {
public static void main(String[] args) {
BaseCookies cookies = null;
BaseSandwich sandwich = null;
BaseBiscuitsFactory factory = null;
// 想吃A店的饼干
factory = new BiscuitsFactoryA();
cookies = factory.createCookies();
sandwich = factory.createSandwich();
cookies.makeCookies();
sandwich.makeSandwich();
// 想吃B店的饼干
factory = new BiscuitsFactoryB();
cookies = factory.createCookies();
sandwich = factory.createSandwich();
cookies.makeCookies();
sandwich.makeSandwich();
}
}
相信到这里也可以看出这样做的好处了吧,这样做的好处就是就算我们现在有了C店、D店、E店等更多的分店,也只需要新增饼干的具体子类和工厂的具体子类就可以了,在我们调用时依旧还是使用饼干的基类和工厂的基类,请不要在意我的客户端使用new工厂子类的方式,我只是懒得写了,在真实的应用中我们根本不需要关系究竟是哪一个子类实现了我们的方法,只需要对其抽象定义和调用就好了,具体的实现在运行时才会确定下来。