设计模式之工厂方法模式

转载请注明出处:http://blog.csdn.net/droyon/article/details/8684094

工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

案例情景:在简单工厂中的那家买粥的生意非茶好,卖粥的招牌很响,他们想在开两家分店,把招牌租出去,允许分店对粥做改良,更新。

两家分店的名字为CongeeStroeA,CongeeStroeB。CongeeStreA家的大米粥含有皮蛋瘦肉,CongeeStreB家的八宝粥里面还有银耳。我们的总店,CongeeStore去年经营的不错,还是固守陈规。

定义一个工厂方法,这个方法用来处理对象的创建。这个方法的具体实现交由子类来完成。

案例代码下载

粥店基类:

public abstract class CongeeStoreBase {
	public CongeeStoreBase(){
	}
	
	public void buyCongee(String name){
		System.out.println("来一份:"+name);
		sellCongee(name);
	}
	
	private void sellCongee(String name){
		Congee congee = getCongee(name);
		congee.takeCup();
		congee.fillCongee();
		congee.sell();
	}
	
	protected abstract Congee getCongee(String name);
}
当我们卖出一份粥时,我们需要调用getCongee方法得到一份粥,但这份粥是什么粥,这个类并不关心,它只需将拿到的粥倒入纸杯,递给用户。在这个流程中,CongeeStroeBase并不知道具体的粥类参与进来了。

工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序关于超类的代码就和子类对象创建解耦了。它通过子类来决定实例化那个对象,以此达到将对象创建过程封装的目的。

我们看看是如何做到的:

三家粥店:

1、CongeeStore.java

public class CongeeStore extends CongeeStoreBase{

	@Override
	protected Congee getCongee(String name) {
		if(name.equals("大米粥")){
			return new Damizhou();
		}else if(name.equals("小米粥")){
			return new Xiaomizhou();
		}else if(name.equals("八宝粥")){
			return new Babaozhou();
		}else {
			return new Congee("null");
		}
	}

}
2、CongeeStoreA.java

public class CongeeStoreA extends CongeeStoreBase{

	@Override
	protected Congee getCongee(String name) {
		if(name.equals("大米粥")){
			return new DamizhouA();
		}else if(name.equals("小米粥")){
			return new Xiaomizhou();
		}else if(name.equals("八宝粥")){
			return new Babaozhou();
		}else {
			return new Congee("null");
		}
	}

}
3、CongeeStoreB.java

public class CongeeStroeB extends CongeeStoreBase{

	@Override
	protected Congee getCongee(String name) {
		if(name.equals("大米粥")){
			return new Damizhou();
		}else if(name.equals("小米粥")){
			return new Xiaomizhou();
		}else if(name.equals("八宝粥")){
			return new BabaozhouB();
		}else {
			return new Congee("null");
		}
	}

}

第二家分店做的大米粥,第三家分店做的八宝粥与众不同。

粥类的实现:

Congee.java

public class Congee {
	private String name;
	
	public Congee(String name){
		this.name = name;
	}
	public void takeCup(){
		System.out.println("拿出一个纸杯");
	}
	public void fillCongee(){
		System.out.println("装入"+name);
	}
	public void sell(){
		System.out.println("卖出这杯粥,价格:"+getPrice(name)+"元");
	}
	
	private double getPrice(String name){
		if(name.equals("大米粥")){return 2;}
		if(name.equals("小米粥")){return 2;}
		if(name.equals("八宝粥")){return 2.5;}
		if(name.equals("黑米粥")){return 2.5;}
		return 0;
	}
}

Babaozhou.java

public class Babaozhou extends Congee{

	public Babaozhou() {
		super("八宝粥");
	}

}

Xiaomizhou.java

public class Xiaomizhou extends Congee{

	public Xiaomizhou() {
		super("小米粥");
	}
	
}

DamizhouA.java

public class DamizhouA extends Congee{

	public DamizhouA() {
		super("大米粥");
	}

	@Override
	public void fillCongee() {
//		super.fillCongee();
		System.out.println("装入"+"皮蛋瘦肉大米粥");
	}


}

BabaozhouB.java

public class BabaozhouB extends Congee{

	public BabaozhouB() {
		super("八宝粥");
	}

	@Override
	public void fillCongee() {
		// TODO Auto-generated method stub
		//super.fillCongee();
		System.out.println("装入"+"银耳八宝粥");
	}
	
	

}

测试主类代码:

Test.java

public class Test {
	public static void main(String args[]){
		//初始化三家店
		CongeeStoreBase no1 = new CongeeStore();
		CongeeStoreBase no2 = new CongeeStoreA();
		CongeeStoreBase no3 = new CongeeStroeB();
		
		//小李想喝大米粥
		no2.buyCongee("大米粥");
		System.out.println("-----小李不喜欢含有皮蛋的大米粥,他发誓再也不去no2买粥了");
		no1.buyCongee("八宝粥");
		System.out.println("-----小李发现no1家的八宝粥不错");
		no3.buyCongee("八宝粥");
		System.out.println("------小李发现no3家的八宝粥含有银耳,他很喜欢,决定以后天天去");
	}
}

测试结果:

来一份:大米粥
拿出一个纸杯
装入皮蛋瘦肉大米粥
卖出这杯粥,价格:2.0元
-----小李不喜欢含有皮蛋的大米粥,他发誓再也不去no2买粥了
来一份:八宝粥
拿出一个纸杯
装入八宝粥
卖出这杯粥,价格:2.5元
-----小李发现no1家的八宝粥不错
来一份:八宝粥
拿出一个纸杯
装入银耳八宝粥
卖出这杯粥,价格:2.5元
------小李发现no3家的八宝粥含有银耳,他很喜欢,决定以后天天去

总结:简单工厂模式把对象的创建封装起来,工厂方法创建了一个框架,让子类决定要如何实现。简单工厂不具备工厂方法的弹性。如果增加新产品,简单工厂需要修改代码,而工厂方法可以通过继承工厂,实现虚方法即可,在设计上更有弹性。

依赖倒置原则:要依赖抽象,不要依赖具体类。不能让高层组件依赖低层组件。两者都应该依赖抽象,围绕抽象解问题,也就是面向抽象编程。

具体解释:

粥店买粥的行为,粥店是高层组件,具体的粥是低层组件。从顶端开始分为以下几步  那个纸盒,装粥,卖粥。所以我的粥店必须有具体的粥。但我们不能依赖具体的类。

现在倒置思考方式,从低层开始思考,每一种粥都是粥,所以所有的粥都有共同的一些特性,所以应该抽离出共同点,构建一个接口。这个接口可以调用具体类的所有行为,这样,我们使用工厂模式将初始化具体类抽离出来,这样高层组件依赖接口粥类,低层具体粥类也依赖接口粥类,从而倒置了编码思考方式。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hailushijie

您的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值