`

工厂模式 Java设计模式笔记

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

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

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

(故事纯属瞎构,代码仅供参考)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics