工厂模式 Java设计模式笔记

[b]工厂模式的作用:[/b]
工厂模式致力于管理实现同一接口的类,它可以事先不必知道哪个类要被使用,而在使用的时候动态的进行类的实例化。
[b]工厂模式的类型:[/b]
一般来说,我们可以把工厂模式分为三种形态:简单工厂、工厂方法、抽象工厂。根据复杂程度的依次提高,他们有不同的使用场景。

[b][size=large]1)简单工厂模式:[/size][/b]
[b]简单工厂模式的作用:[/b]
简单工厂模式又称作静态工厂模式,可以根据实例时变量的不同而返回不同的类,从而实现进行类的动态实例化。
[b]简单工厂模式的元素:[/b]
我们可以给简单工厂模式提取三个角色:工厂类、抽象产品、具体产品。这里边工厂类是核心,是它被调用的时候创建具体产品对象。
[b]简单工厂模式的故事场景:[/b]
时间回到东汉末年,冀州一处市场上叫刘备关羽张飞的三位商人,意气相投,在人家桃树园子里歃血为盟,开辟一段历史新篇章。
[b]角色提取及代码实现:[/b]
先说,刘备、关羽、张飞三位都是生意人,做买卖的,我们提取出一个生意人的角色,做抽象产品。

/**
* @author Veiking
* 生意人的抽象接口
*/
public interface Trader {
//生意人共有的行为特征,最买卖
public void trading();
}

刘关张都是生意人啊,于是我们定义刘关张三位大商人,遵循这个接口,做具体产品。

/**
* @author Veiking
* 大生意人刘关张
*/
public class Liubei implements Trader {
@Override
public void trading() {
System.out.println("我专业卖鞋子!");
}
}
public class Guanyu implements Trader {
@Override
public void trading() {
System.out.println("我专业卖豆子!");
}
}
public class Zhangfei implements Trader{
@Override
public void trading() {
System.out.println("我专业卖肉肉!");
}
}

这哥仨很会做生意,后来都做到王侯的份上了,那肯定要读点私塾,了解下商人的基本素养啥的,于是乎,我们提取一个培养刘关张三位杰出青年的商人学校,算是工厂类吧。

/**
* @author Veiking
* 商人私塾类,刘关张排号一二三,喊谁出来谁
*/
public class TraderShool {
//这方法是专门产生具体对象的,根据参数产生对应的人
public Trader getTrader(int order){
if(order==1){
return new Liubei();
}else if(order==2){
return new Guanyu();
}else if(order==3){
return new Zhangfei();
}else{
System.out.println("弄错认了吧,没这位!");
return null;
}
}
}

接下来,我们来到菜市场,验证下。

/**
* @author Veiking
* 菜市场,各色商人出来露脸的地方
*/
public class Market {
public static void main(String[] args) {
Trader trader = null;
TraderShool traderShool = new TraderShool();
//一号!刘备出厂
trader = traderShool.getTrader(1);
trader.trading();
//二号!关羽出厂
trader = traderShool.getTrader(2);
trader.trading();
//三号!张飞出厂
trader = traderShool.getTrader(3);
trader.trading();
}
}

[b]小结:[/b]
我们去菜市场,肯定要碰到商人,但具体跟谁打交道,之前是不确定的,简单工厂模式的好处就是我们需要跟哪位商人打交道,传入相应的参数就行了。如果还需要添加一些新商人,比如赵云啦,曹操啦谁的,不用管刘关张三位的代码,只需新定义他们各自具体的产品类就行了,唯一不好的就是要动动商人学校那个工厂类,得让新来商人的也培训下,这点略有违背开闭原则。

[b][size=large]2)工厂方法模式:[/size][/b]
[b]工厂方法模式的作用:[/b]
工厂方法模式略有升级,其是定义一个接口,自己不管,让子类来决定实例化哪一个类,将实例化的主动权交给子类。在工厂方法中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类,这个核心工厂坐地升级,变成了一个抽象工厂,仅提供子类需要实现的接口,而不再处理具体的工作细节。
[b]工厂方法模式的元素:[/b]
工厂方法模式相比简单工厂多了一个角色,一共四个:抽象工厂,具体工厂、抽象产品、具体产品。这里抽象工厂成了模式的核心,任何用来生产创建具体产品对象的工厂,都必须实现这个类。
[b]工厂方法模式的故事场景:[/b]
还是东汉末年,冀州大商人,关羽专业卖豆子,当然红豆绿豆啥豆都有卖,那买卖做得是风生水起好的不行,卖豆卖到后来裂土封侯,令世人惊叹不已,以至于现在都有很多商人跪拜他老人家!
[b]角色提取及代码实现:[/b]
既然是卖豆,不管啥豆子都是豆子,必然要提出来一个豆子类,做抽象产品

/**
* @author Veiking
* 豆子的集合,抽象接口
*/
public interface Bean {
//所有豆子都有味道,尝一尝,什么味儿
void taste();
}

红豆绿豆,都是好豆,我们要分别定义出红绿两种豆子,作具体产品

/**
* @author Veiking
* 分别定义红豆绿豆,各有各的香,各有各的味儿
*/
public class RedBean implements Bean {
@Override
public void taste() {
System.out.println("绿豆嘎嘣脆,绿豆香喷喷");
}
}
public class GreenBean implements Bean {
@Override
public void taste() {
System.out.println("红豆嘎嘣脆,红豆香喷喷");
}
}

豆子们都圆咕噜,活蹦乱跳的,肯定不能随地乱堆乱放,弄不好混一起就麻烦了,所以要用个袋子装着,我们抽取一个袋子类,做抽象工厂
/** 
* @author Veiking
* 袋子的结合,专门盛放豆子的,可以得到豆子
*/
public interface Bag {
//抓一把,满是豆子
public Bean getBean();
}

光有袋子这个概念也不行,要注意,红豆得放红袋子里,绿豆得放绿袋子里,没的话人家来买豆子,两种豆子傻傻分不清,生意能做好么,所以,我们要定义两种袋子,分别盛放不同豆子

/**
* @author Veiking
* 分别定义红袋子绿袋子,红袋装红豆,绿袋装绿豆
*/
public class RedBag implements Bag {
@Override
public Bean getBean() {
return new RedBean();
}
}
public class GreenBag implements Bag {
@Override
public Bean getBean() {
return new GreenBean();
}
}

好,豆子准备好了,装豆的袋子也都有了,我们就要来到关羽的店子里,买不买不说,可以先看看
/** 
* @author Veiking
* 关家店,经营红绿豆子
*/
public class GuanyuShop {
public static void main(String[] args) {
//走进关家豆店
Bag bag = null;//我们还不知道啥袋子
Bean bean = null;//我们更不知道啥豆子
//开始东张西望
bag = new RedBag(); //左边摆了个红袋子
bean = bag.getBean();//一伸手,一把红豆
bean.taste();//放嘴里尝尝,一嘴红豆味
//明显生吃味道不行,再看看
bag = new GreenBag();//右边摆了个红袋子
bean = bag.getBean();//一伸手,一把绿豆
bean.taste();//放嘴里尝尝,一嘴绿豆味
//生吃味道都不咋样,不买了
}
}

[b]小结:[/b]
从这里我们可以看出,进了关家店之后,我们只需要关心装豆的袋子,并不用操心豆子是怎么来的,去红袋子里,肯定能得到红豆,去绿袋子,也肯定能得到绿豆,也就是说袋子这个工厂方法隐藏了产生豆子这一细节。如果关家店要扩大业务,想卖黄豆黑豆扁豆啥的,也不用修改抽象工厂、抽象产品二类,只需要定义各种豆子,添加具体产品类,再添加相对应的具体工厂类即可,这样关家豆店的业务拓展会非常便捷,也不难解释后来关羽生意能做那么大的原因,这就完全符合“开闭原则”。不好的是,每添加一种豆子,都要用专门的袋子去装,豆子种类多了,袋子添的也麻烦,但这都是不得已的事儿了。

[b][size=large]3)抽象工厂模式:[/size][/b]
[b]抽象工厂模式的作用:[/b]
抽象工厂模式跟工厂方法模式基本相同,都是用来提供创建一组或有相互依赖关系的接口,而无需关心他们具体的类。不同的是,抽象工厂模式的抽象工厂,不局限于提供一个产品,而是一个产品族,产品族之间既可以有逻辑关系,也可以是简单的归类从属。
[b]抽象工厂模式的元素:[/b]
抽象工厂模式跟工厂方法模式一样,也是四个角色:抽象工厂,具体工厂、抽象产品、具体产品。
[b]抽象工厂模式的故事场景:[/b]
还是东汉末年,刘关张三位大商人,分别经营鞋子、豆子和肉三种商品,但是生意做得好,没交通工具不行,他们各有一匹宝马,刘备的叫的卢,关于的叫赤兔,张飞的叫王追。这三匹马,那是日行千里,负重万斤,为他们兄弟生意做大做强,出了不少力气。
[b]角色提取及代码实现:[/b]
在这个故事场景里,首先我们要提取商品和交通工具这两种类,做抽象产品

/**
* @author Veiking
* 分别定义两种类型的东西,交通工具和商品
*/
public interface AbstractTransport {
//展示交通工具特性
public void showTransport();
}
public interface AbstractGoods {
//展示商品货物特性
public void showGoods();
}

所有的马,都遵循交通工具的特征,只是名字时速不一样,我们可以这样做具体实现

/**
* @author Veiking
* 定义具体的交通工具和商品,分别实现他们所属的抽象类型接口
*/
public class Horse implements AbstractTransport{
private String name;
private int speed;
//初始化,每个交通工具都要赋予特别的属性
public Horse(String name, int speed){
this.name = name;
this.speed = speed;
}
//展示交通工具特性,名字跟时速,都要曝下
@Override
public void showTransport() {
System.out.println("我的交通工具叫\'" + this.name + "\',它能日行" + this.speed + "里!");
}
}

现在故事中的商品货物,不管是鞋子豆子还有肉,统统都是商品,只是类型有异,重量不同,我们可以这样实现

public class Goods implements AbstractGoods {
private String type;
private int weight;
//初始化,每个商品要赋予特别的属性
public Goods(String type, int weight){
this.type = type;
this.weight = weight;
}
//展示商品货物特性,什么商品,多少,要说清楚
@Override
public void showGoods() {
System.out.println("我卖的货物是\'" + this.type + "\',我店里有" + this.weight + "斤这玩意儿!");
}
}

好了,抽象类产品跟具体产品都准备好了,我们看看,刘关张每个人都有各自的工厂,来产生各自的特色商品跟交通工具,所以要提出一个抽象工厂,这个工厂的功能呢,就是产生货物跟交通工具

/**
* @author Veiking
* 定义抽象工厂,负责产生交通工具,产生商品货物
*/
public interface AbstractFactory {
//产生交通工具
public AbstractTransport createTransport();
//产生商品货物
public AbstractGoods createGoods();
}

刘关张三位商人做运输的马匹名字、属性都不一样,货物类型、重量也截然不同,具体的工厂肯定也不能一样,我们来定义他们各自的宝贝工厂

/**
* @author Veiking
* 分别定义刘关张三位的具体工厂,负责产生各自的交通工具和具体商品货物
*/
public class LiubeiFactory implements AbstractFactory {
//获得的卢马,日行八百
@Override
public AbstractTransport createTransport() {
return new Horse ("的卢", 800);
}
//刘备卖鞋子很给力,400斤鞋子!
@Override
public AbstractGoods createGoods() {
return new Goods ("鞋子", 400);
}
}
public class GuanyuFactory implements AbstractFactory {
//关于专属赤兔马,那个时代很有名的千里马
@Override
public AbstractTransport createTransport() {
return new Horse ("赤兔", 1000);
}
//关羽卖豆讲究效率,现在还有300斤各色豆子!
@Override
public AbstractGoods createGoods() {
return new Goods ("豆子", 300);
}
}
public class ZhangfeiFactory implements AbstractFactory {
//张飞的王追,也不是盖的,日行九百里!
@Override
public AbstractTransport createTransport() {
return new Horse ("王追", 900);
}
//500斤肉已出,坐等抢购
@Override
public AbstractGoods createGoods() {
return new Goods ("肉肉", 500);
}
}

所有的材料都准备好了,刘关张三位富豪各自携带自己的宝贝工厂,在冀州的一处街市,出场了

/**
* @author Veiking
* 菜市场,商人巨贾出没
*/
public class Market {
public static void main(String[] args) {
//菜市场中热闹非凡,各种类型的东西都已经上场备齐
AbstractTransport transport = null;
AbstractGoods goods = null;
AbstractFactory factory = null;
//刘备先来一步
factory = new LiubeiFactory();
transport = factory.createTransport();
transport.showTransport();
goods = factory.createGoods();
goods.showGoods();
//关羽紧接着出场
factory= new GuanyuFactory();
transport = factory.createTransport();
transport.showTransport();
goods = factory.createGoods();
goods.showGoods();
//张飞也来了
factory = new ZhangfeiFactory();
transport = factory.createTransport();
transport.showTransport();
goods = factory.createGoods();
goods.showGoods();
}
}

[b]小结:[/b]
我们可以看到,抽象工厂模式隔离了具体类的生成,用户并不关心具体是什么被创建了,刘关张只需关心自己所拥有的宝贝工厂如何产生东西即可。我们仔细注意可以发现,抽象工厂模式的抽象产品可以是一个或多个,当只有一个的产品的情况下,也就跟工厂方法一样了。

(故事纯属瞎构,代码仅供参考)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值