设计模式-工厂方法和抽象工厂方法

工厂方法

  工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。

  

        工厂方法是抽象的,所以依赖子类来处理对象的创建。

  工厂方法必须返回一个产品。超类中定义的方法,通常使用到工厂方法的返回值。

  工厂方法将客户(也就是超类中的代码,如orderPizza())和实际创建具体产品的代码分隔开来。

  工厂方法可能需要参数(也可能不需要)来指定所需要的产品。

 

工厂方法模式定义

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

  

抽象工厂类和具体工厂类 可以使用泛型实现

产品的输入参数类型可以自行设置,通常为String.Enum.Class等


ConcreteCreator可以有一个或多个,选择了子类,则选择了实际创建的工厂方法。

这个具体的工厂可以只创建一种对象,也可以根据传入的参数创建不同的对象。

工厂方法和Creator并不总是抽象的,也可以提供默认的具体实现。

工厂方法模式例子

Demo1

interface Service {
		void method1();
		void method2();
}
interface ServiceFactory{
	 	Service getService();
}
class implementation1 implements Service{
		implementation1() {}
		public void method1()  { System.out.println("Implementation1 method1");}
		public void method2() {  System.out.println("Implementation1 method2");}	
}
class Implementation1Factory implements ServiceFactory {
		public Service getService() {
				return new implementation1();
		}
}
class implementation2 implements Service{
	implementation2() {}
	public void method1()  { System.out.println("Implementation2 method1");}
	public void method2() {  System.out.println("Implementation2 method2");}	
}
class Implementation2Factory implements ServiceFactory {
	public Service getService() {
			return new implementation2();
	}
}
public class Factories {
	public static void  serviceConsumer( ServiceFactory fact) {
			Service s = fact.getService();
			s.method1();
			s.method2();
	}
		
	public static void main(String[] args) {
		// TODO Auto-generated method stub
			serviceConsumer(new Implementation1Factory());
			serviceConsumer(new Implementation2Factory());
	}
}
Demo2 实现不同种类匹萨的制造

import java.util.ArrayList;
//产品抽象类
 abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList toppings = new ArrayList();
 
	void prepare() {
		System.out.println("Preparing " + name);
		System.out.println("Tossing dough...");
		System.out.println("Adding sauce...");
		System.out.println("Adding toppings: ");
		for (int i = 0; i < toppings.size(); i++) {
			System.out.println("   " + toppings.get(i));
		}
	}
  
	void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}

	void cut() {
		System.out.println("Cutting the pizza into diagonal slices");
	}
	void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
	public String getName() {
		return name;
	}
	public String toString() {
		StringBuffer display = new StringBuffer();
		display.append("---- " + name + " ----\n");
		display.append(dough + "\n");
		display.append(sauce + "\n");
		for (int i = 0; i < toppings.size(); i++) {
			display.append((String )toppings.get(i) + "\n");
		}
		return display.toString();
	}
}
import java.util.ArrayList;
//产品抽象类
public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList toppings = new ArrayList();
 
	void prepare() {
		System.out.println("Preparing " + name);
		System.out.println("Tossing dough...");
		System.out.println("Adding sauce...");
		System.out.println("Adding toppings: ");
		for (int i = 0; i < toppings.size(); i++) {
			System.out.println("   " + toppings.get(i));
		}
	}
  
	void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}

	void cut() {
		System.out.println("Cutting the pizza into diagonal slices");
	}
	void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
	public String getName() {
		return name;
	}
	public String toString() {
		StringBuffer display = new StringBuffer();
		display.append("---- " + name + " ----\n");
		display.append(dough + "\n");
		display.append(sauce + "\n");
		for (int i = 0; i < toppings.size(); i++) {
			display.append((String )toppings.get(i) + "\n");
		}
		return display.toString();
	}
}
//具体工厂2
public class ChicagoPizzaStore extends PizzaStore {

	Pizza createPizza(String item) {
        	if (item.equals("cheese")) {
            		return new ChicagoStyleCheesePizza();
        	} else if (item.equals("veggie")) {
        	    	return new ChicagoStyleVeggiePizza();
        	} else if (item.equals("clam")) {
        	    	return new ChicagoStyleClamPizza();
        	} else if (item.equals("pepperoni")) {
            		return new ChicagoStylePepperoniPizza();
        	} else return null;
	}
}
//具体工厂一
public class NYPizzaStore extends PizzaStore {

	Pizza createPizza(String item) {
		if (item.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (item.equals("veggie")) {
			return new NYStyleVeggiePizza();
		} else if (item.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (item.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		} else return null;
	}
}
//具体产品
public class ChicagoStyleCheesePizza extends Pizza {

	public ChicagoStyleCheesePizza() { 
		name = "Chicago Style Deep Dish Cheese Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
	}
 
	void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}
//具体产品
public class ChicagoStyleClamPizza extends Pizza {
	public ChicagoStyleClamPizza() {
		name = "Chicago Style Clam Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Frozen Clams from Chesapeake Bay");
	}
 
	void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}
//具体产品
public class ChicagoStyleVeggiePizza extends Pizza {
	public ChicagoStyleVeggiePizza() {
		name = "Chicago Deep Dish Veggie Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Black Olives");
		toppings.add("Spinach");
		toppings.add("Eggplant");
	}
 
	void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}
//具体产品
public class NYStyleCheesePizza extends Pizza {

	public NYStyleCheesePizza() { 
		name = "NY Style Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
	}
}
//具体产品
public class NYStyleClamPizza extends Pizza {

	public NYStyleClamPizza() {
		name = "NY Style Clam Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Fresh Clams from Long Island Sound");
	}
}//具体产品
public class NYStyleVeggiePizza extends Pizza {

	public NYStyleVeggiePizza() {
		name = "NY Style Veggie Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Garlic");
		toppings.add("Onion");
		toppings.add("Mushrooms");
		toppings.add("Red Pepper");
	}
}
//测试
 public class PizzaTestDrive {
 
	public static void main(String[] args) {
		PizzaStore nyStore = new NYPizzaStore();
		PizzaStore chicagoStore = new ChicagoPizzaStore();
 
		Pizza pizza = nyStore.orderPizza("cheese");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoStore.orderPizza("cheese");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");

		pizza = nyStore.orderPizza("clam");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoStore.orderPizza("clam");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");

		pizza = nyStore.orderPizza("veggie");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoStore.orderPizza("veggie");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");
	}
}


抽象工厂方法定义

  抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要关心实际产出的具体产品是什么。

  抽象工厂方法是工厂方法模式的升级版本,在多个业务品种,业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式

类图:

 对一定问题的解决方案。抽象工厂模式面对的问题是多产品等级结构的系统设计。

在学习抽象工厂具体实例之前,应该明白两个重要的概念:产品族和产品等级。

产品族:是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如AMD的CPU和ADM芯片的主板,组成一个家族。Intel的CPU和Intel芯片的主板,又组成一个家族。而这两个家族都来自于两个产品等级:CPU,主板。一个等级结构是由相同的结构的产品组成,示意图如下:

理解这个产品结构是理解抽象工厂模式的关键所在,从上图可以看出,抽象工厂模式的每个工厂创造出来的都是一族产品,而不是一个或者一组。组是可以随意组合的!其实工厂方法模式和抽象工厂模式就这点点差别

通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码,我们的代码将从实际工厂解耦,以便在不同上下文实现各式各样的工厂,制造出各种不同的产品,因为代码从实际的产品解耦,所以我们可以替换不同的产品来取得不同行为。一个简单的例子如下:

抽象工厂方法模式例子

编程实现不同汽车族的制造,代码中BmwCar和BenzCar就是两个产品树(产品层次结构);而BenzSportsCar和BmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzBusinessCar也是一个产品族。


<pre name="code" class="java">    //抽象产品(Bmw和Audi同理)  
    abstract class BenzCar{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    //具体产品(Bmw和Audi同理)  
    class BenzSportCar extends BenzCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BenzSportCar-----------------------");  
        }  
    }  
    class BenzBusinessCar extends BenzCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BenzBusinessCar-----------------------");  
        }  
    }  
      
    abstract class BmwCar{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    class BmwSportCar extends BmwCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BmwSportCar-----------------------");  
        }  
    }  
    class BmwBusinessCar extends BmwCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BmwBusinessCar-----------------------");  
        }  
    }  
      
    abstract class AudiCar{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    class AudiSportCar extends AudiCar{  
        public void drive(){  
            System.out.println(this.getName()+"----AudiSportCar-----------------------");  
        }  
    }  
    class AudiBusinessCar extends AudiCar{  
        public void drive(){  
            System.out.println(this.getName()+"----AudiBusinessCar-----------------------");  
        }  
    }  
      
      
    //抽象工厂  
    abstract class Driver3{  
        public abstract BenzCar createBenzCar(String car) throws Exception;  
          
        public abstract BmwCar createBmwCar(String car) throws Exception;  
          
        public abstract AudiCar createAudiCar(String car) throws Exception;  
    }  
    //具体工厂  
    class SportDriver extends Driver3{  
        public BenzCar createBenzCar(String car) throws Exception {  
            return new BenzSportCar();  
        }  
        public BmwCar createBmwCar(String car) throws Exception {  
            return new BmwSportCar();  
        }  
        public AudiCar createAudiCar(String car) throws Exception {  
            return new AudiSportCar();  
        }  
    }  
    class BusinessDriver extends Driver3{  
        public BenzCar createBenzCar(String car) throws Exception {  
            return new BenzBusinessCar();  
        }  
        public BmwCar createBmwCar(String car) throws Exception {  
            return new BmwBusinessCar();  
        }  
        public AudiCar createAudiCar(String car) throws Exception {  
            return new AudiBusinessCar();  
        }  
    }  
      
    //老板  
    public class BossAbstractFactory {  
      
        public static void main(String[] args) throws Exception {  
              
            Driver3 d = new BusinessDriver();  
            AudiCar car = d.createAudiCar("");  
            car.drive();  
        }  
    }  



 

工厂方法和抽象工厂对比

抽象工厂方法是利用工厂方法实现的

  仔细观察,抽象工厂的每个方法实际上看起来都像是工厂方法,每个方法都被声明为抽象,而子类的方法覆盖这些方法来创建某些对象,这正是工厂方法的做法

  每个方法都被声明成抽象,而子类的方法覆盖这些方法来创建某些对象。

  抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品,利用实现抽象工厂的子类来提供这些具体的做法。所以,在抽象工厂中利用工厂方法实现生产方法是很自然的做法。

 

工厂方法与抽象工厂的不同点

  工厂方法用的是继承,需要扩展一个类,并覆盖它的工厂方法。

  抽象工厂是通过对象的组合,对象的创建被实现在工厂接口所暴露出来的方法中。它的优点是可以把一群相关的产品集合起来。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值