工厂模式 Java设计模式笔记
程序员文章站
2022-07-14 08:58:18
...
工厂模式的作用:
工厂模式致力于管理实现同一接口的类,它可以事先不必知道哪个类要被使用,而在使用的时候动态的进行类的实例化。
工厂模式的类型:
一般来说,我们可以把工厂模式分为三种形态:简单工厂、工厂方法、抽象工厂。根据复杂程度的依次提高,他们有不同的使用场景。
1)简单工厂模式:
简单工厂模式的作用:
简单工厂模式又称作静态工厂模式,可以根据实例时变量的不同而返回不同的类,从而实现进行类的动态实例化。
简单工厂模式的元素:
我们可以给简单工厂模式提取三个角色:工厂类、抽象产品、具体产品。这里边工厂类是核心,是它被调用的时候创建具体产品对象。
简单工厂模式的故事场景:
时间回到东汉末年,冀州一处市场上叫刘备关羽张飞的三位商人,意气相投,在人家桃树园子里歃血为盟,开辟一段历史新篇章。
角色提取及代码实现:
先说,刘备、关羽、张飞三位都是生意人,做买卖的,我们提取出一个生意人的角色,做抽象产品。
刘关张都是生意人啊,于是我们定义刘关张三位大商人,遵循这个接口,做具体产品。
这哥仨很会做生意,后来都做到王侯的份上了,那肯定要读点私塾,了解下商人的基本素养啥的,于是乎,我们提取一个培养刘关张三位杰出青年的商人学校,算是工厂类吧。
接下来,我们来到菜市场,验证下。
小结:
我们去菜市场,肯定要碰到商人,但具体跟谁打交道,之前是不确定的,简单工厂模式的好处就是我们需要跟哪位商人打交道,传入相应的参数就行了。如果还需要添加一些新商人,比如赵云啦,曹操啦谁的,不用管刘关张三位的代码,只需新定义他们各自具体的产品类就行了,唯一不好的就是要动动商人学校那个工厂类,得让新来商人的也培训下,这点略有违背开闭原则。
2)工厂方法模式:
工厂方法模式的作用:
工厂方法模式略有升级,其是定义一个接口,自己不管,让子类来决定实例化哪一个类,将实例化的主动权交给子类。在工厂方法中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类,这个核心工厂坐地升级,变成了一个抽象工厂,仅提供子类需要实现的接口,而不再处理具体的工作细节。
工厂方法模式的元素:
工厂方法模式相比简单工厂多了一个角色,一共四个:抽象工厂,具体工厂、抽象产品、具体产品。这里抽象工厂成了模式的核心,任何用来生产创建具体产品对象的工厂,都必须实现这个类。
工厂方法模式的故事场景:
还是东汉末年,冀州大商人,关羽专业卖豆子,当然红豆绿豆啥豆都有卖,那买卖做得是风生水起好的不行,卖豆卖到后来裂土封侯,令世人惊叹不已,以至于现在都有很多商人跪拜他老人家!
角色提取及代码实现:
既然是卖豆,不管啥豆子都是豆子,必然要提出来一个豆子类,做抽象产品
红豆绿豆,都是好豆,我们要分别定义出红绿两种豆子,作具体产品
豆子们都圆咕噜,活蹦乱跳的,肯定不能随地乱堆乱放,弄不好混一起就麻烦了,所以要用个袋子装着,我们抽取一个袋子类,做抽象工厂
光有袋子这个概念也不行,要注意,红豆得放红袋子里,绿豆得放绿袋子里,没的话人家来买豆子,两种豆子傻傻分不清,生意能做好么,所以,我们要定义两种袋子,分别盛放不同豆子
好,豆子准备好了,装豆的袋子也都有了,我们就要来到关羽的店子里,买不买不说,可以先看看
小结:
从这里我们可以看出,进了关家店之后,我们只需要关心装豆的袋子,并不用操心豆子是怎么来的,去红袋子里,肯定能得到红豆,去绿袋子,也肯定能得到绿豆,也就是说袋子这个工厂方法隐藏了产生豆子这一细节。如果关家店要扩大业务,想卖黄豆黑豆扁豆啥的,也不用修改抽象工厂、抽象产品二类,只需要定义各种豆子,添加具体产品类,再添加相对应的具体工厂类即可,这样关家豆店的业务拓展会非常便捷,也不难解释后来关羽生意能做那么大的原因,这就完全符合“开闭原则”。不好的是,每添加一种豆子,都要用专门的袋子去装,豆子种类多了,袋子添的也麻烦,但这都是不得已的事儿了。
3)抽象工厂模式:
抽象工厂模式的作用:
抽象工厂模式跟工厂方法模式基本相同,都是用来提供创建一组或有相互依赖关系的接口,而无需关心他们具体的类。不同的是,抽象工厂模式的抽象工厂,不局限于提供一个产品,而是一个产品族,产品族之间既可以有逻辑关系,也可以是简单的归类从属。
抽象工厂模式的元素:
抽象工厂模式跟工厂方法模式一样,也是四个角色:抽象工厂,具体工厂、抽象产品、具体产品。
抽象工厂模式的故事场景:
还是东汉末年,刘关张三位大商人,分别经营鞋子、豆子和肉三种商品,但是生意做得好,没交通工具不行,他们各有一匹宝马,刘备的叫的卢,关于的叫赤兔,张飞的叫王追。这三匹马,那是日行千里,负重万斤,为他们兄弟生意做大做强,出了不少力气。
角色提取及代码实现:
在这个故事场景里,首先我们要提取商品和交通工具这两种类,做抽象产品
所有的马,都遵循交通工具的特征,只是名字时速不一样,我们可以这样做具体实现
现在故事中的商品货物,不管是鞋子豆子还有肉,统统都是商品,只是类型有异,重量不同,我们可以这样实现
好了,抽象类产品跟具体产品都准备好了,我们看看,刘关张每个人都有各自的工厂,来产生各自的特色商品跟交通工具,所以要提出一个抽象工厂,这个工厂的功能呢,就是产生货物跟交通工具
刘关张三位商人做运输的马匹名字、属性都不一样,货物类型、重量也截然不同,具体的工厂肯定也不能一样,我们来定义他们各自的宝贝工厂
所有的材料都准备好了,刘关张三位富豪各自携带自己的宝贝工厂,在冀州的一处街市,出场了
小结:
我们可以看到,抽象工厂模式隔离了具体类的生成,用户并不关心具体是什么被创建了,刘关张只需关心自己所拥有的宝贝工厂如何产生东西即可。我们仔细注意可以发现,抽象工厂模式的抽象产品可以是一个或多个,当只有一个的产品的情况下,也就跟工厂方法一样了。
(故事纯属瞎构,代码仅供参考)
工厂模式致力于管理实现同一接口的类,它可以事先不必知道哪个类要被使用,而在使用的时候动态的进行类的实例化。
工厂模式的类型:
一般来说,我们可以把工厂模式分为三种形态:简单工厂、工厂方法、抽象工厂。根据复杂程度的依次提高,他们有不同的使用场景。
1)简单工厂模式:
简单工厂模式的作用:
简单工厂模式又称作静态工厂模式,可以根据实例时变量的不同而返回不同的类,从而实现进行类的动态实例化。
简单工厂模式的元素:
我们可以给简单工厂模式提取三个角色:工厂类、抽象产品、具体产品。这里边工厂类是核心,是它被调用的时候创建具体产品对象。
简单工厂模式的故事场景:
时间回到东汉末年,冀州一处市场上叫刘备关羽张飞的三位商人,意气相投,在人家桃树园子里歃血为盟,开辟一段历史新篇章。
角色提取及代码实现:
先说,刘备、关羽、张飞三位都是生意人,做买卖的,我们提取出一个生意人的角色,做抽象产品。
/** * @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(); } }
小结:
我们去菜市场,肯定要碰到商人,但具体跟谁打交道,之前是不确定的,简单工厂模式的好处就是我们需要跟哪位商人打交道,传入相应的参数就行了。如果还需要添加一些新商人,比如赵云啦,曹操啦谁的,不用管刘关张三位的代码,只需新定义他们各自具体的产品类就行了,唯一不好的就是要动动商人学校那个工厂类,得让新来商人的也培训下,这点略有违背开闭原则。
2)工厂方法模式:
工厂方法模式的作用:
工厂方法模式略有升级,其是定义一个接口,自己不管,让子类来决定实例化哪一个类,将实例化的主动权交给子类。在工厂方法中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类,这个核心工厂坐地升级,变成了一个抽象工厂,仅提供子类需要实现的接口,而不再处理具体的工作细节。
工厂方法模式的元素:
工厂方法模式相比简单工厂多了一个角色,一共四个:抽象工厂,具体工厂、抽象产品、具体产品。这里抽象工厂成了模式的核心,任何用来生产创建具体产品对象的工厂,都必须实现这个类。
工厂方法模式的故事场景:
还是东汉末年,冀州大商人,关羽专业卖豆子,当然红豆绿豆啥豆都有卖,那买卖做得是风生水起好的不行,卖豆卖到后来裂土封侯,令世人惊叹不已,以至于现在都有很多商人跪拜他老人家!
角色提取及代码实现:
既然是卖豆,不管啥豆子都是豆子,必然要提出来一个豆子类,做抽象产品
/** * @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();//放嘴里尝尝,一嘴绿豆味 //生吃味道都不咋样,不买了 } }
小结:
从这里我们可以看出,进了关家店之后,我们只需要关心装豆的袋子,并不用操心豆子是怎么来的,去红袋子里,肯定能得到红豆,去绿袋子,也肯定能得到绿豆,也就是说袋子这个工厂方法隐藏了产生豆子这一细节。如果关家店要扩大业务,想卖黄豆黑豆扁豆啥的,也不用修改抽象工厂、抽象产品二类,只需要定义各种豆子,添加具体产品类,再添加相对应的具体工厂类即可,这样关家豆店的业务拓展会非常便捷,也不难解释后来关羽生意能做那么大的原因,这就完全符合“开闭原则”。不好的是,每添加一种豆子,都要用专门的袋子去装,豆子种类多了,袋子添的也麻烦,但这都是不得已的事儿了。
3)抽象工厂模式:
抽象工厂模式的作用:
抽象工厂模式跟工厂方法模式基本相同,都是用来提供创建一组或有相互依赖关系的接口,而无需关心他们具体的类。不同的是,抽象工厂模式的抽象工厂,不局限于提供一个产品,而是一个产品族,产品族之间既可以有逻辑关系,也可以是简单的归类从属。
抽象工厂模式的元素:
抽象工厂模式跟工厂方法模式一样,也是四个角色:抽象工厂,具体工厂、抽象产品、具体产品。
抽象工厂模式的故事场景:
还是东汉末年,刘关张三位大商人,分别经营鞋子、豆子和肉三种商品,但是生意做得好,没交通工具不行,他们各有一匹宝马,刘备的叫的卢,关于的叫赤兔,张飞的叫王追。这三匹马,那是日行千里,负重万斤,为他们兄弟生意做大做强,出了不少力气。
角色提取及代码实现:
在这个故事场景里,首先我们要提取商品和交通工具这两种类,做抽象产品
/** * @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(); } }
小结:
我们可以看到,抽象工厂模式隔离了具体类的生成,用户并不关心具体是什么被创建了,刘关张只需关心自己所拥有的宝贝工厂如何产生东西即可。我们仔细注意可以发现,抽象工厂模式的抽象产品可以是一个或多个,当只有一个的产品的情况下,也就跟工厂方法一样了。
(故事纯属瞎构,代码仅供参考)
上一篇: 多线程 & 异步调用 的理解
下一篇: 简洁的在线按钮css生成器