软件设计模式-装饰器模式-工厂模式

本文探讨了软件设计模式中的装饰器模式和工厂模式。装饰器模式允许在运行时为类添加新特性,而不修改基类,通过继承实现扩展。文章通过饮料和配料的例子展示了如何使用装饰器模式实现动态扩展。接着,介绍了工厂模式,包括使用工厂对象的示例和工厂方法的使用,强调了工厂模式在动态增加产品类型中的灵活性。最后提到了抽象工厂模式在实现产品家族中的应用,允许创建多个对象实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

装饰器模式

之前我们说过软件设计模式的一个典型特征就是 使用面向接口而不是继承的编程 但是有种情况是特殊的 例如我们的装饰器模式 之所以需要装饰器模式 是因为需要运行时对某个类进行修饰 由于我们设计模式的准则是开放-关闭原则 即扩展性要较高 并且关闭修改 即我们肯定是不能够修改基类的 还要能增加新的特性 这就是为什么代码中不论是Beverage(饮料)还是Condiment(配料) 都需要一个共同的基类 因为要想不修改底层代码 还要增加新的特性 那么这不就是类继承的用法吗 虽然设计模式中我们不推荐使用继承 但要因事物而变 不能固定思维 通过使用继承我们可以将配料和饮料都定为同一类型 这样调用父类的方法就没有问题 最后通过类似于递归的方式 我们可以得到最终的结果 并且可以很好的保持运行时的扩展 可以可以看到我们的main方法中可以叠加不同种类的配料 这就达到了扩展 并且如果我们想增加一个配方 那么我们只需要再继承一个配料基类 或者 饮料基类 而不用改变基类的任何代码 然后最后在main方法中加以包装即可

/**  
* @Title: StarBuzzTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月8日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月8日 下午7:36:30
*/
/**  
* @ClassName: StarBuzzTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月8日  
*    
*/

/**
 * 
* @ClassName: Beverage  
* @Description: 定义一个抽象基类 之所以这里用基类而不是接口 是因为调料必须和饮料是同一个基类! 不然装饰器模式就是空谈
* @author Nigel  
* @date 2019年12月8日  
*
 */
abstract class Beverage{
	protected String description;
	
	public String getDescription() {
		return description;
	}
	
	/**
	 * 
	* @Title: cost  
	* @Description: 这个cost方法是需要被所有继承的实体类所重写的 因为每个实体必定有一个价钱 并且价钱也是不一致的
	* @return    
	* @return Double    
	* @throws
	 */
	abstract Double cost();
}

/**
 * 
* @ClassName: CondimentDecorator  
* @Description: 调料必须继承饮料类 这样才能发挥装饰类的特点!
* @author Nigel  
* @date 2019年12月8日  
*
 */
abstract class CondimentDecorator extends Beverage{
	protected Beverage superClassBeverage;
	/**
	 * 
	* <p>Title: getDescription</p>  
	* <p>Description: 每个调料对应的修饰自然也是不一样的
	* @return  
	* @see Beverage#getDescription()
	 */
	public abstract String getDescription();
}

/**
 * 
* @ClassName: Espresso  
* @Description: 此时为实体类 即实体饮料
* @author Nigel  
* @date 2019年12月8日  
*
 */
class Espresso extends Beverage {
	
	public Espresso() {
		// TODO Auto-generated constructor stub
		description = "Espresso";
	}
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return 1.99;
	}
	
}

class HouseBlend extends Beverage {
	
	/**  
	* 创建一个新的实例 HouseBlend.  
	*    
	*/
	public HouseBlend() {
		// TODO Auto-generated constructor stub
		description = "HouseBlend";
	}
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return .89;
	}
	
}

class DarkRoast extends Beverage {
	
	/**  
	* 创建一个新的实例 DarkRoast.  
	*    
	*/
	public DarkRoast() {
		// TODO Auto-generated constructor stub
		description = "DarkRoast";
	}
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return .99;
	}
	
}

class Decaf extends Beverage {
	
	/**  
	* 创建一个新的实例 Decaf.  
	*    
	*/
	public Decaf() {
		// TODO Auto-generated constructor stub
		description = "Decaf";
	}
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return 1.05;
	}
	
}


//接下来让调料进行实例化 其基类也是Beverage
class Mocha extends CondimentDecorator {
	 
	
	/**  
	* 创建一个新的实例 Mocha.  需要提供一个参数来附加到对应的饮料实体上
	*    
	*/
	public Mocha(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	/**
	* <p>Title: getDescription</p>  
	* <p>Description:之所以要重写getDescription 是因为对于调料而言 我们是要叠加上去的 所以还需要返回上级的描述!
	* @return  
	* @see CondimentDecorator#getDescription()  
	*/  
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage.getDescription() + "Mocha";
	}

	/**
	* <p>Title: cost</p>  
	* <p>Description: </p>  
	* @return  
	* @see Beverage#cost()  
	*/  
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .20;
	}
	
}

class Milk extends CondimentDecorator {
	
	/**  
	* 创建一个新的实例 Milk.  
	*    
	*/
	public Milk(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage.description + "Milk";
	}

	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .10;
	}
	
}

class SoyaBean extends CondimentDecorator {
	/**  
	* 创建一个新的实例 SoyaBean.  
	*    
	*/
	public SoyaBean(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
				
	}

	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage + "SoyaBean";
	}

	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .15;
	}
	
}

class Whip extends CondimentDecorator {
	
	/**  
	* 创建一个新的实例 Whip.  
	*    
	*/
	public Whip(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage.getDescription() + "Whip";
	}
	
	/**
	 * 
	* <p>Title: cost</p>  
	* <p>Description: 以一种递归的方式来计算cost价格
	* @return  
	* @see Beverage#cost()
	 */
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .10;
	}
	
}

public class StarBuzzTest {

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
		//进行测试
		System.out.print("不加配料的情况下:");
		Beverage decafBeverage = new Decaf();//实例化一个decaf低咖啡因
		System.out.println(decafBeverage.getDescription());//打印一下description
		System.out.print("价钱:");
		System.out.println(decafBeverage.cost());
		//加上Milk后的描述和价钱
		System.out.print("加Milk后的情况:");
		CondimentDecorator decafWithMilk = new Milk(decafBeverage);
		System.out.println( decafWithMilk.getDescription() );
		System.out.print("价钱:");
		System.out.printf("%.2f\n", decafWithMilk.cost());
		//加Mocha后的情况
		CondimentDecorator decafWithMilkAndMocha = new Mocha(decafWithMilk);
		System.out.printf("再加上Mocha后的情形:");
		System.out.println(decafWithMilkAndMocha.getDescription());
		System.out.print("价钱:");
		System.out.println(decafWithMilkAndMocha.cost());
		
	}

}



为Beverage加size1(大杯 中杯 小杯)之后的修改代码 我们只需要修改对应的配料的cost方法后

/**  
* @Title: StarBuzzTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月8日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月8日 下午7:36:30
*/
/**  
* @ClassName: StarBuzzTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月8日  
*    
*/

/**
 * 
* @ClassName: Beverage  
* @Description: 定义一个抽象基类 之所以这里用基类而不是接口 是因为调料必须和饮料是同一个基类! 不然装饰器模式就是空谈
* @author Nigel  
* @date 2019年12月8日  
*
 */
abstract class Beverage{
	protected String description;
	protected final static Integer BIG_SIZE = 9;
	protected final static Integer SMALL_SIZE = 3;
	protected final static Integer MEDIUM_SIZE = 6;
	protected Integer size;
	
	public Integer getSize() {
		return this.size;
	}
	
	public String getDescription() {
		return description;
	}
	
	/**
	 * 
	* @Title: cost  
	* @Description: 这个cost方法是需要被所有继承的实体类所重写的 因为每个实体必定有一个价钱 并且价钱也是不一致的
	* @return    
	* @return Double    
	* @throws
	 */
	abstract Double cost();
}

/**
 * 
* @ClassName: CondimentDecorator  
* @Description: 调料必须继承饮料类 这样才能发挥装饰类的特点!
* @author Nigel  
* @date 2019年12月8日  
*
 */
abstract class CondimentDecorator extends Beverage{
	protected Beverage superClassBeverage;
	/**
	 * 
	* <p>Title: getDescription</p>  
	* <p>Description: 每个调料对应的修饰自然也是不一样的
	* @return  
	* @see Beverage#getDescription()
	 */
	public abstract String getDescription();
	
	
}

/**
 * 
* @ClassName: Espresso  
* @Description: 此时为实体类 即实体饮料
* @author Nigel  
* @date 2019年12月8日  
*
 */
class Espresso extends Beverage {
	
	public Espresso() {
		// TODO Auto-generated constructor stub
		description = "Espresso";
		size = Beverage.MEDIUM_SIZE;//默认中杯
	}
	
	/**
	 * 
	* 创建一个新的实例 Espresso.  可以指定对应的是大杯还是小杯
	*  
	* @param size
	 */
	public Espresso(Integer size) {
		this.size = size;
		description = "Espresso";
	}
	
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return 1.99;
	}
	
}

class HouseBlend extends Beverage {
	
	/**  
	* 创建一个新的实例 HouseBlend.  
	*    
	*/
	public HouseBlend() {
		// TODO Auto-generated constructor stub
		description = "HouseBlend";
	}
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return .89;
	}
	
}

class DarkRoast extends Beverage {
	
	/**  
	* 创建一个新的实例 DarkRoast.  
	*    
	*/
	public DarkRoast() {
		// TODO Auto-generated constructor stub
		description = "DarkRoast";
	}
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return .99;
	}
	
}

class Decaf extends Beverage {
	
	/**  
	* 创建一个新的实例 Decaf.  
	*    
	*/
	public Decaf() {
		// TODO Auto-generated constructor stub
		description = "Decaf";
	}
	
	public Decaf(Integer size) {
		this.size = size;
		description = "Decaf";
	}
	
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return 1.05;
	}
	
}


//接下来让调料进行实例化 其基类也是Beverage
class Mocha extends CondimentDecorator {
	 
	
	/**  
	* 创建一个新的实例 Mocha.  需要提供一个参数来附加到对应的饮料实体上
	*    
	*/
	public Mocha(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	/**
	* <p>Title: getDescription</p>  
	* <p>Description:之所以要重写getDescription 是因为对于调料而言 我们是要叠加上去的 所以还需要返回上级的描述!
	* @return  
	* @see CondimentDecorator#getDescription()  
	*/  
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage.getDescription() + "Mocha";
	}

	/**
	* <p>Title: cost</p>  
	* <p>Description: </p>  
	* @return  
	* @see Beverage#cost()  
	*/  
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		//这里增长size可以这样写
		Double sizeCost = 0D;
		if (superClassBeverage.getSize() == Beverage.BIG_SIZE) {
			sizeCost += 0.20;
		} else if (superClassBeverage.getSize() == Beverage.MEDIUM_SIZE) {
			sizeCost += 0.15;
		} else if (superClassBeverage.getSize() == Beverage.SMALL_SIZE) {
			sizeCost += 0.10;
		}
		return sizeCost + superClassBeverage.cost() + .20;
	}
	
}

class Milk extends CondimentDecorator {
	
	/**  
	* 创建一个新的实例 Milk.  
	*    
	*/
	public Milk(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage.description + "Milk";
	}

	@Override
	Double cost() {
		// TODO Auto-generated method stub
		Double sizeCost = 0D;
		if (superClassBeverage.getSize() == Beverage.BIG_SIZE) {
			sizeCost += 0.20;
		} else if (superClassBeverage.getSize() == Beverage.MEDIUM_SIZE) {
			sizeCost += 0.15;
		} else if (superClassBeverage.getSize() == Beverage.SMALL_SIZE) {
			sizeCost += 0.10;
		}
		return sizeCost + superClassBeverage.cost() + .10;
	}
	
}

class SoyaBean extends CondimentDecorator {
	/**  
	* 创建一个新的实例 SoyaBean.  
	*    
	*/
	public SoyaBean(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
		
	}

	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage + "SoyaBean";
	}

	@Override
	Double cost() {
		// TODO Auto-generated method stub
		Double sizeCost = 0D;
		if (superClassBeverage.getSize() == Beverage.BIG_SIZE) {
			sizeCost += 0.20;
		} else if (superClassBeverage.getSize() == Beverage.MEDIUM_SIZE) {
			sizeCost += 0.15;
		} else if (superClassBeverage.getSize() == Beverage.SMALL_SIZE) {
			sizeCost += 0.10;
		}
		return sizeCost + superClassBeverage.cost() + .15;
	}
	
}

class Whip extends CondimentDecorator {
	
	/**  
	* 创建一个新的实例 Whip.  
	*    
	*/
	public Whip(Beverage beverage) {
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return superClassBeverage.getDescription() + "Whip";
	}
	
	/**
	 * 
	* <p>Title: cost</p>  
	* <p>Description: 以一种递归的方式来计算cost价格
	* @return  
	* @see Beverage#cost()
	 */
	@Override
	Double cost() {
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .10;
	}
	
}

public class StarBuzzTest {

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
		//进行测试
		System.out.print("不加配料的情况下:");
		Beverage decafBeverage = new Decaf(Beverage.BIG_SIZE);//实例化一个decaf低咖啡因
		System.out.println(decafBeverage.getDescription());//打印一下description
		System.out.print("价钱:");
		System.out.println(decafBeverage.cost());
		//加上Milk后的描述和价钱
		System.out.print("加Milk后的情况:");
		CondimentDecorator decafWithMilk = new Milk(decafBeverage);
		System.out.println( decafWithMilk.getDescription() );
		System.out.print("价钱:");
		System.out.printf("%.2f\n", decafWithMilk.cost());
		//加Mocha后的情况
		CondimentDecorator decafWithMilkAndMocha = new Mocha(decafWithMilk);
		System.out.printf("再加上Mocha后的情形:");
		System.out.println(decafWithMilkAndMocha.getDescription());
		System.out.print("价钱:");
		System.out.println(decafWithMilkAndMocha.cost());
		
	}

}

/*不加配料的情况下:Decaf
价钱:1.05
加Milk后的情况:DecafMilk
价钱:1.15
再加上Mocha后的情形:DecafMilkMocha
价钱:1.35*/



工厂模式

使用工厂对象的示例

我们现在有如下的需求 我们需要一个披萨店订购不同的披萨 ** 披萨店家应该是只负责做披萨 而不需要关心它的种类该是啥 为了能动态的增加可以做的pizza类型 我们专门设定了一个pizza的工厂对象 这个工厂对象用来专门生产pizza 即返回对应的pizza实体** 这样可以使pizza店不会因为直接使用new而创造出具体的类出来 创建具体的类的工作由工厂来负责

/**  
* @Title: PizzaFactoryTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月9日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月9日 上午11:33:27
*/


interface Pizza {
	void prepare();
	void cook();
	void cut();
	void box();//包装
}

//下面创建一些Pizza的实体类 从而才能在披萨工厂中创建对应的实体对象
class CheesePizza implements Pizza{

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println("prepare " + this.getClass().getName());
	}

	@Override
	public void cook() {
		// TODO Auto-generated method stub
		System.out.println("cook " + this.getClass().getName());
	}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

	@Override
	public void cut() {
		// TODO Auto-generated method stub
		System.out.println("cut CheesePizza");
	}

	@Override
	public void box() {
		// TODO Auto-generated method stub
		System.out.println("box CheesePizza");
	}
	
}

class PepperoniPizza implements Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cook() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cut() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void box() {
		// TODO Auto-generated method stub
		
	}
	
}

class ClamPizza implements Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cook() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cut() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void box() {
		// TODO Auto-generated method stub
		
	}
	
}

class VeggiePizza implements Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cook() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cut() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void box() {
		// TODO Auto-generated method stub
		
	}
	
}
/**
 * 
* @ClassName: SimplePizzaFactory  
* @Description: 只用来产出pizza种类的工厂类  专门负责对象的产生 这样我们可以重复利用产生不同对象的披萨对象(即该例中的变化)
* @author Nigel  
* @date 2019年12月9日  
*
 */
class SimplePizzaFactory {
	
	public static final int CHEESE_PIZZA = 1;
	public static final int PEPPERONI_PIZZA = 0;
	public static final int CLAM_PIZZA = 2;
	public static final int VEGGIE_PIZZA = 3;
	/**
	 * @return 
	 * 
	* @Title: createPizza  
	* @Description: 接收一个披萨的种类 用来创建不同的披萨饼 之所以是静态方法 是因为这样我们就可以不通过实例化方法产生pizza类!
	* @param type    
	* @return void    
	* @throws
	 */
	public static Pizza createPizza(int type) {
		Pizza pizza = null;
		switch (type) {
		case CHEESE_PIZZA:
			pizza = new CheesePizza();
			break;
		case PEPPERONI_PIZZA:
			pizza = new PepperoniPizza();
			break;
		case CLAM_PIZZA:
			pizza = new ClamPizza();
			break;
		case VEGGIE_PIZZA:
			pizza = new VeggiePizza();
			break;
		}
		return pizza;//将创建好的pizza对象返回!
	}
}



/**  
* @ClassName: PizzaFactoryTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月9日  
*    
*/
public class PizzaFactoryTest {

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
		//这里实现pizza的配送 这里不再使用new运算符获得一个"具体的对象" 而是通过pizza工厂类的静态方法实现对pizza对象的获取
		int myPizzaType = SimplePizzaFactory.CHEESE_PIZZA;
		orderPizza(myPizzaType);
	}
	
	public static void orderPizza(int type) {
		Pizza myPizza = SimplePizzaFactory.createPizza(type);
		//然后委任任务给具体的pizza
		myPizza.cook();
		myPizza.cut();
		myPizza.box();
	}

}

使用工厂方法的示例

如果我们此时想要在不同的地区开区域连锁店 那么每个区域就应该要有不同的特色 此时如果我们依旧让工厂去生产 那么对于区域的局部性而言 其弹性就会不足 我们无法合理的进行扩展 因为披萨店是抽象的 我们无法应用具体的区域特色 例如披萨独特的口味 原料 等 此时我们可以使用工厂方法 即我们将之前的pizza店提取出来作为基类 并且让createPizza设定为抽象 但是制作流程保持一致 让对应的区域店来负责生产披萨的区域特色处理

示例代码如下

/**  
* @Title: PizzaFactoryTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月9日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月9日 上午11:33:27
*/


abstract class Pizza {
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println("prepare " + this.getClass().getName());
	}
	
	public void cook() {
		// TODO Auto-generated method stub
		System.out.println("cook " + this.getClass().getName());
	}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

	public void cut() {
		// TODO Auto-generated method stub
		System.out.println("cut CheesePizza");
	}

	public void box() {
		// TODO Auto-generated method stub
		System.out.println("box CheesePizza");
	}
}

//下面创建一些Pizza的实体类 从而才能在披萨工厂中创建对应的实体对象
class CheesePizza extends Pizza{
}

class PepperoniPizza extends Pizza {
}

class ClamPizza extends Pizza {
}

class VeggiePizza extends Pizza {
}

class NYStyleCheesePizza extends Pizza {
	
}

class NYStyleClamPizza extends Pizza {
	
}

class ChicagoStyleClamPizza extends Pizza {
	
}

class ChicagoStyleCheesePizza extends Pizza {
	
}

/**
 * 
* @ClassName: SimplePizzaFactory  
* @Description: 只用来产出pizza种类的工厂类  专门负责对象的产生 这样我们可以重复利用产生不同对象的披萨对象(即该例中的变化)
* @author Nigel  
* @date 2019年12月9日  
*
 */
class SimplePizzaFactory {
	
	public static final int CHEESE_PIZZA = 1;
	public static final int PEPPERONI_PIZZA = 0;
	public static final int CLAM_PIZZA = 2;
	public static final int VEGGIE_PIZZA = 3;
	/**
	 * @return 
	 * 
	* @Title: createPizza  
	* @Description: 接收一个披萨的种类 用来创建不同的披萨饼 之所以是静态方法 是因为这样我们就可以不通过实例化方法产生pizza类!
	* @param type    
	* @return void    
	* @throws
	 */
	public static Pizza createPizza(int type) {
		Pizza pizza = null;
		switch (type) {
		case CHEESE_PIZZA:
			pizza = new CheesePizza();
			break;
		case PEPPERONI_PIZZA:
			pizza = new PepperoniPizza();
			break;
		case CLAM_PIZZA:
			pizza = new ClamPizza();
			break;
		case VEGGIE_PIZZA:
			pizza = new VeggiePizza();
			break;
		}
		return pizza;//将创建好的pizza对象返回!
	}
}

/**
 * 
* @ClassName: PizzaStore  
* @Description: 此时将披萨店设置为基类 让区域店继承实现特色处理 同时也可以很好的处理创建具体对象的分隔问题
* @author Nigel  
* @date 2019年12月9日  
*
 */
abstract class PizzaStore {
	public void orderPizza(int type) {
		//这里我们仍然实现了抽象 披萨店仍然只创建pizza 因为点披萨的过程仍然是固定的
		Pizza pizza = createPizza(type);
		//下面仍然是委任
		pizza.prepare();
		pizza.cook();
		pizza.cut();
		pizza.box();
	}
	
	abstract public Pizza createPizza(int type);
}

class NYStyleCheesePizzaStore extends PizzaStore {
	
	/**
	 * 
	* <p>Title: createPizza</p>  
	* <p>Description: 这里进行了重写createPizza方法 
	* @param type
	* @return  
	* @see PizzaStore#createPizza(int)
	 */
	@Override
	public Pizza createPizza(int type) {
		// TODO Auto-generated method stub
		Pizza pizza = null;
		switch (type) {
		case SimplePizzaFactory.CHEESE_PIZZA:
			pizza = new NYStyleCheesePizza();
			break;
		case SimplePizzaFactory.PEPPERONI_PIZZA:
			pizza = new PepperoniPizza();
			break;
		case SimplePizzaFactory.CLAM_PIZZA:
			pizza = new NYStyleClamPizza();
			break;
		case SimplePizzaFactory.VEGGIE_PIZZA:
			pizza = new VeggiePizza();
			break;
		}
		return pizza;//将创建好的pizza对象返回!
	}
	
}

class ChicagoStyleCheesePizzaStore extends PizzaStore {
	
	/**
	 * 
	* <p>Title: createPizza</p>  
	* <p>Description: 这里进行了重写createPizza方法 
	* @param type
	* @return  
	* @see PizzaStore#createPizza(int)
	 */
	@Override
	public Pizza createPizza(int type) {
		// TODO Auto-generated method stub
		Pizza pizza = null;
		switch (type) {
		case SimplePizzaFactory.CHEESE_PIZZA:
			pizza = new ChicagoStyleCheesePizza();
			break;
		case SimplePizzaFactory.PEPPERONI_PIZZA:
			pizza = new PepperoniPizza();
			break;
		case SimplePizzaFactory.CLAM_PIZZA:
			pizza = new ChicagoStyleClamPizza();//ChicagoStyleCheesePizza
			break;
		case SimplePizzaFactory.VEGGIE_PIZZA:
			pizza = new VeggiePizza();
			break;
		}
		return pizza;//将创建好的pizza对象返回!
	}
	
}

/**
 * 
* @ClassName: NYStyleCheesePizza  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月9日  
*
 */

/**  
* @ClassName: PizzaFactoryTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月9日  
*    
*/
public class PizzaFactoryTest {

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
		//这里实现pizza的配送 这里不再使用new运算符获得一个"具体的对象" 而是通过pizza工厂类的静态方法实现对pizza对象的获取
		System.out.println("点NY风格的两种披萨:");
		NYStyleCheesePizzaStore storeOfNY = new NYStyleCheesePizzaStore();
		storeOfNY.orderPizza(SimplePizzaFactory.CHEESE_PIZZA);
		storeOfNY.orderPizza(SimplePizzaFactory.CLAM_PIZZA);
		System.out.println("点Chicago风格的两种披萨:");
		ChicagoStyleCheesePizzaStore storeOfChicago = new ChicagoStyleCheesePizzaStore();
		storeOfChicago.orderPizza(SimplePizzaFactory.CHEESE_PIZZA);
		storeOfChicago.orderPizza(SimplePizzaFactory.CLAM_PIZZA);
	}
}

利用工厂对象实现原料分配(抽象工厂实现产品家族)

如果此时我们想在每个区域店的区域中开设我们自己的工厂 即我们想把生产原料的工作交给工厂对象来执行
利用抽象工厂 我们可以实现多个create的抽象 即多个对象的实例化

此时的示例代码如下(部分)
仅演示抽象工厂的创建部分

ructor stub
		description = this.getClass().getName();
	}
}

abstract class Cheese {
	protected String description;

	public String getDescription() {
		return description;
	}
}

class ReggianoCheese extends Cheese {
	/**  
	* 创建一个新的实例 ReggianoCheese.  
	*    
	*/
	public ReggianoCheese() {
		// TODO Auto-generated constructor stub
		description = this.getClass().getName();
	}
}

abstract class Veggies {
	protected String description;

	public String getDescription() {
		return description;
	}
}

class Garlic extends Veggies{
	/**  
	* 创建一个新的实例 BlackVeggies.  
	*    
	*/
	public Garlic() {
		// TODO Auto-generated constructor stub
		description = this.getClass().getName();
	}
}

class Onion extends Veggies{
	/**  
	* 创建一个新的实例 BlackVeggies.  
	*    
	*/
	public Onion() {
		// TODO Auto-generated constructor stub
		description = this.getClass().getName();
	}
}

class Mushroom extends Veggies{
	/**  
	* 创建一个新的实例 BlackVeggies.  
	*    
	*/
	public Mushroom() {
		// TODO Auto-generated constructor stub
		description = this.getClass().getName();
	}
}


/*
 * 简单的披萨工厂接口
 */
interface PizzaIngredientFactory {
	Dough createDough();
	Sause createSauce();
	Cheese createCheese();
	Veggies[] createVeggies();
}

/**
 * 
* @ClassName: NYPizzaIngredientFactory  
* @Description: 原料是具有地方特色的
* @author Nigel  
* @date 2019年12月9日  
*
 */
class NYPizzaIngredientFactory implements PizzaIngredientFactory {

	@Override
	public Dough createDough() {
		// TODO Auto-generated method stub
		return new ThinCrustDough();
	}

	@Override
	public Sause createSauce() {
		// TODO Auto-generated method stub
		return new MarinaraSause();
	}

	@Override
	public Cheese createCheese() {
		// TODO Auto-generated method stub
		return new ReggianoCheese();
	}

	@Override
	public Veggies[] createVeggies() {
		// TODO Auto-generated method stub
		Veggies[] veggies = { new Garlic(), new Onion(), new Mushroom() };
		return veggies;
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值