欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

工厂模式 Java设计模式笔记

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

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();
	}
}

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

(故事纯属瞎构,代码仅供参考)