python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)

十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式

 

我看了《Head First 设计模式》P109--P133 这25页,讲述了我们为什么要用工厂模式,里面用做pizza的例子讲的特别细腻。看完了就能很清楚的知道为什么要用工厂模式。

年龄越大越不喜欢一知半解,深刻的了解某些未知的事或物以后,它再出现就不怕了

 

 

 #'New'有什么不对劲?

在技术上,new没有错,这是语言的基础部分。真正的犯人是我们的老朋友 ‘改变’, 以及它是如何影响new使用的。

 

如果代码是通过接口而写,通过多态,可以与任何新类实现该接口。

但是当代码使用大量的具体类时,那就麻烦了,因为一旦加入新的具体类,就必须改变代码。意思是代码没 " 对修改关闭"。想用新的具体类来扩展代码,必须重新打开它。

 

这可咋办?  只能改代码

 

 

 

 很明显,如果实例化某些具体类,将使orderPizza()出问题,没办法让orderPizza()对修改关闭,

但是咱们还是能很明显的看出哪些会变,哪些不会变,这个时候就可以考虑封装了,

 

 

   

 上面这些引出了下面的简单工厂模式

 

#简单工厂模式

1)算是定义吧

简单工厂模式其实并不是一个模设计模式,反而比较像一种编程习惯,还请不要把这个习惯认为是“工厂模式”。

 不要因为简单工厂不是一个真正的模式,就忽略它的用法。

 

2)类图

 

 3)举个例子(java)

public class PizzaStore {
    SimplePizzaFactory factory;
 
    public PizzaStore(SimplePizzaFactory factory){
        this.factory=factory;
    }
 
    public Pizza orderPizza(String type){
        Pizza pizza;
        pizza=factory.createPizza(type);
 
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

############################

public class SimplePizzaFactory {
    public Pizza createPizza(String type){
        Pizza pizza=null;
            if(type.equals("cheese")){
                pizza=new CheesePizza();
            }else if (type.equals("greek")){
                pizza=new GreekPizza();
            }else if(type.equals("pepperoni")){
                pizza=new PepperoniPizza();
            }else if (type.equals("clam")){
                pizza=new ClamPizza();
            }else if (type.equals("veggie")){
                pizza=new VeggiePizza();
            }
        return pizza;
    }
}


########################################################
public abstract class Pizza {
    String name;
    String dough;
    String sauce;
 
    void prepare(){
        System.out.print("Preparing");
    };
    void bake(){
        System.out.print("Baking");
    };
    void cut(){
        System.out.print("cut");
    };
    void box(){
        System.out.print("box");
    };
 
}
 
 
public class VeggiePizza extends Pizza{
}
 
public class ClamPizza extends Pizza {
}
 
public class PepperoniPizza extends Pizza {
}
 
public class PepperoniPizza extends Pizza {
}

#################################

public static void main(String[] args) {
    PizzaStore store=new PizzaStore();
    Pizza pizza=store.orderPizza("cheese");
    System.out.println("eat Pizza");
}

 

 

 

 4)举个例子(python)

 

 

 

#工厂方法模式

#引入

 #匹萨生意火爆,现在有很多人要开加盟店,不同地区的加盟店口味有差异。PizzaStore有个不错的订单系统,希望所有加盟店对订单的处理一致。

各区域匹萨店之间的差异在于他们制作匹萨的风味(比如 NYStyle 饼薄, ChicagoStyle 饼厚等),我们现在让createPizza()来应对这些变化负责创建正确种类的匹萨。

做法是让PizzaStore的各个子类负责定义自己的createPizza()方法。所以我们会得到PizzaStore的具体类。

 

#定义

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

 

所有工厂模式都是用来封装对象的创建。工厂方法模式(Factory Method Pattern) 通过让子类决定该创建的对象是什么,来达到对象创建的过程封装的目的。

 

原本是由一个对象负责所有具体的实例化,现在变成一群子类负责实例化

 

 

 #类图

 

 

 

 

 

 

#举个例子(java)

public abstract class PizzaStore {
    

    public Pizza orderPizza(String type){
        Pizza pizza;
        pizza=createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    abstract Pizza createPizza(String type);

}

###########################################################
public class NYPizzaStore extends PizzaStore{
    Pizza createPizza(String item){
        if(item.equals("cheese")){
            return new NYStyleCheesePizza();
        }else if (item.equals("greek")){
            return new NYStyleGreekPizza();
        }else if(item.equals("pepperoni")){
            return new NYStylePepperoniPizza();
        }else if (item.equals("clam")){
            return new NYStyleClamPizza();
        }else if (item.equals("veggie")){
            return new NYStyleVeggiePizza();
        }else return null
}

########
public class ChicagoPizzaStore extends PizzaStore {
    Pizza createPizza(String item){
        if(item.equals("cheese")){
            return new ChicagoStyleCheesePizza();
        }else if (item.equals("greek")){
            return new ChicagoStyleGreekPizza();
        }else if(item.equals("pepperoni")){
            return new ChicagoStylePepperoniPizza();
        }else if (item.equals("clam")){
            return new ChicagoStyleClamPizza();
        }else if (item.equals("veggie")){
            return new ChicagoStyleVeggiePizza();
        }else return null;
    }

}


##########################################################
public abstract class Pizza {
    String name;
    String dough;
    String sauce;

    void prepare(){

    }
    void bake(){

    }
    void cut(){

    }
    void box(){

    }
}

##############
public class NYStyleCheesePizza extends Pizza {
    public NYStyleCheesePizza(){
        name="NY Style Sauce and Cheese Pizza";
        dough="Thin Crust Dough";
        sauce="Marinara Sauce";

    }
}


########


public class NYStyleClamPizza extends Pizza {

}

######
public class NYStyleGreekPizza extends Pizza{

}

####

public class NYStylePepperoniPizza extends Pizza {

}
#######

public class NYStyleVeggiePizza extends Pizza {

}
#########

public class ChicagoStyleCheesePizza extends Pizza {
    public ChicagoStyleCheesePizza(){
        name="Chicago Style Sauce and Cheese Pizza";
        dough="Thick Crust Dough";
        sauce="Plum Tomato Sauce";

    }
}

#########
public class ChicagoStyleGreekPizza extends Pizza{

}
########

public class ChicagoStylePepperoniPizza extends Pizza {

}

#######
public class ChicagoStyleClamPizza extends Pizza{

}
######
public class ChicagoStyleVeggiePizza extends Pizza {

}

#####################################################################
public class javatest1 {
    public static void main(String[] args) throws IOException,ClassNotFoundException{
        PizzaStore nyStore=new NYPizzaStore();
        PizzaStore chicagoStore=new ChicagoPizzaStore();
        Pizza pizza=nyStore.orderPizza("cheese");
        System.out.println("eat NYStylePizza");

        pizza = chicagoStore.orderPizza("cheese");
        System.out.println("eat ChicagoStylePizza");
    }
}

 

#举个例子(python)  

class Person(object):
	def __init__(self,name):
		self.name = name
	
	def work(self):
		print(self.name+"工作开始了")
 
		axe = Stone_Factory().create_axe()
 
		axe.cut_tree()
 
class Axe(object):
	def __init__(self,name):
		self.name = name
 
	def cut_tree(self):
		print("使用%s斧头砍树"%self.name)
 
class StoneAxe(Axe):
 
	def cut_tree(self):
		print("使用石斧头砍树")
 
class SteelAxe(Axe):
 
	def cut_tree(self):
		print("使用铁斧头砍树")
 
class Tree(object):
	pass
 
#工厂类
'''
class Factory(object):
	@staticmethod
	def create_axe(type):
		if type == "stone":
			return StoneAxe("花岗岩斧头")
		if type == "steel":
			return SteelAxe("铁斧头")
'''
class Factory(object):
	
	def create_axe(self):
		pass
 
class Stone_Factory(Factory):
	def create_axe(self):
		return StoneAxe("花岗岩斧头")
 
class Steel_Factory(Factory):
	def create_axe(self):
		return SteelAxe("铁斧头")

 code来自https://blog.csdn.net/Mr_Quiet/article/details/80998337

 

#抽象工厂模式

 

 #引入

纽约匹萨店生意火爆,越来越好,需要开好多家纽约披萨店,芝加哥也是面临同样的情况。为了保证质量,就得控制原料。所以我们得建造原料工厂,来生产不同区域的原料。

 

#定义

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

 

允许客户用抽象的借口创建一组产品,不需要知道实际产出的具体产品是什么,这样客户就从具体的产品解耦了。

 

#结构图

 

 

 

 #使用场景

)客户端不依赖于产品类实例如何被创建、实现等细节

)强调一系列相关的产品对象(属于统一产品族)一起使用创建对象需要大量重复的代码

)提供一个产品类的库,所以的产品以同样或者大部分相同的接口出现,从而使客户端不依赖具体实现

 

#优点

实现解耦

 

 #缺

)规定了所有可能被创建的产品集合,产品族扩展新的产品困难,需要修改抽象工厂的接口

)增加了系统的抽象性和理解难度

 

 

#举个例子(java)

public interface Cheese {

}
#############
public interface Pepperoni {

}
##########
public interface Sauce {

}

##################
public interface Clams {

}
public class BlackOlives implements Veggies {

}

#########
public interface Dough {

}
##########
public interface Veggies {

}

######################################################################
public class MozzarellaCheese implements Cheese{

}
########
public class ReggianoCheese implements Cheese {

}
#####

public class Eggplant implements Veggies {

}
#####
public class Garlic implements Veggies{

}
#######
public class Mushroom implements Veggies {

}
###########
public class RedPepper implements Veggies{

}
########
public class Spinach implements Veggies{

}
#####
public class FreshClams implements Clams{

}

######
public class FrozenClams implements Clams{

}

#######
public class MarinaraSauce implements Sauce {

}
#########
public class PlumTomatoSauce implements Sauce {
}
########
public class SlicedPepperoni implements Pepperoni{

}
#########
public class SlicePepperoni implements Pepperoni{

}
########
public class ThinCrustDough implements Dough {

}
########
public class ThickCrustDough implements Dough {

}
########################################################
public interface PizzaIngredientFactory {

	public Sauce createSauce();
	public Cheese createCheese();
	public Veggies[] createVeggies();
	public Pepperoni createPepperoni();
	public Clams createClam();
	public Dough createDough();
}
###################
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
	public Dough createDough(){
		return new ThinCrustDough();
	}
	public Sauce createSauce(){
		return new MarinaraSauce();
	}
	public Cheese createCheese(){
		return new ReggianoCheese();
	}
	public Veggies[] createVeggies(){
		Veggies veggies[]={new Garlic(),new Mushroom(),new RedPepper()};
		return veggies;
	}
	public Pepperoni createPepperoni(){
		return new SlicePepperoni();
	}
	public Clams createClam(){
		return new FreshClams();
	}
}

#########

public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
	public Dough createDough(){
		return new ThickCrustDough();
	}
	public Sauce createSauce(){
		return new PlumTomatoSauce();
	}
	public Cheese createCheese(){
		return new MozzarellaCheese();
	}
	public Veggies[] createVeggies(){
		Veggies veggies[]={new BlackOlives(),new Spinach(),new Eggplant()};
		return veggies;
	}
	public Pepperoni createPepperoni(){
		return new SlicedPepperoni();
	}
	public Clams createClam(){
		return new FrozenClams();
	}
}

#######




###############################################
public abstract class Pizza {
	String name;
    Dough dough;
    Sauce sauce;
    Veggies veggies[];
    Cheese cheese;
    Pepperoni pepperoni;
    Clams clam;

	abstract void prepare();
	
	void bake(){
		System.out.print("Baking");
	};
	
	void cut(){
		System.out.print("cut");
	};
	
	void box(){
		System.out.print("box");
	};
	
	void setName(String name){
		this.name=name;
	}
	
	String getName(){
		return name;
	}
	
	public String toString(){
		return name;		
	}
}
###############
public class CheesePizza extends Pizza{
	PizzaIngredientFactory ingreditentFactory;
	public CheesePizza(PizzaIngredientFactory ingredientFactory){
		this.ingreditentFactory=ingredientFactory;
	}
	
	void prepare(){
		System.out.print("Preparing"+name);
		dough=ingreditentFactory.createDough();
		sauce=ingreditentFactory.createSauce();
		cheese=ingreditentFactory.createCheese();				
	}
}

#############
public class ClamPizza extends Pizza {
	PizzaIngredientFactory ingredientFactory;
	
	public ClamPizza(PizzaIngredientFactory ingredientFactory){
		
		this.ingredientFactory=ingredientFactory;
	}
	
	void prepare(){
		System.out.print("Preparing"+name);
		dough=ingredientFactory.createDough();
		sauce=ingredientFactory.createSauce();
		clam=ingredientFactory.createClam();				
	}		
}

######################
public class PepperoniPizza extends Pizza {
	PizzaIngredientFactory ingreditentFactory;
	public PepperoniPizza(PizzaIngredientFactory ingredientFactory){
		this.ingreditentFactory=ingredientFactory;
	}
	
	void prepare(){
		System.out.print("Preparing"+name);
		dough=ingreditentFactory.createDough();
		sauce=ingreditentFactory.createSauce();
		cheese=ingreditentFactory.createCheese();				
	}
}
################
public class VeggiePizza extends Pizza {
	PizzaIngredientFactory ingreditentFactory;
	public VeggiePizza(PizzaIngredientFactory ingredientFactory){
		this.ingreditentFactory=ingredientFactory;
	}
	
	void prepare(){
		System.out.print("Preparing"+name);
		dough=ingreditentFactory.createDough();
		sauce=ingreditentFactory.createSauce();
		cheese=ingreditentFactory.createCheese();				
	}

}
###############################################################################################
public abstract class PizzaStore {
	
    public Pizza orderPizza(String type){
        Pizza pizza;
        pizza=createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    abstract Pizza createPizza(String type);

}
############################
public class NYPizzaStore extends PizzaStore{
	protected Pizza createPizza(String item){
		Pizza pizza=null;
		PizzaIngredientFactory nyIngredientFactory=new NYPizzaIngredientFactory();
		if(item.equals("cheese")){
			pizza=new CheesePizza(nyIngredientFactory);
			pizza.setName("New York Style Cheese Pizza");
		}else if(item.equals("veggie")){
			pizza=new VeggiePizza(nyIngredientFactory);
			pizza.setName("New York Style Veggie Pizza");
		}else if(item.equals("clam")){
			pizza=new ClamPizza(nyIngredientFactory);
			pizza.setName("New York Style Clam Pizza");			
		}else if(item.equals("pepperoni")){
			pizza=new PepperoniPizza(nyIngredientFactory);
			pizza.setName("New York Style Pepperoni Pizza");
		}
        return pizza;
	}
}
###################
public class ChicagoPizzaStore extends PizzaStore{
	protected Pizza createPizza(String item){
		Pizza pizza=null;
		PizzaIngredientFactory nyIngredientFactory=new ChicagoPizzaIngredientFactory();
		if(item.equals("cheese")){
			pizza=new CheesePizza(nyIngredientFactory);
			pizza.setName("New York Style Cheese Pizza");
		}else if(item.equals("veggie")){
			pizza=new VeggiePizza(nyIngredientFactory);
			pizza.setName("New York Style Veggie Pizza");
		}else if(item.equals("clam")){
			pizza=new ClamPizza(nyIngredientFactory);
			pizza.setName("New York Style Clam Pizza");			
		}else if(item.equals("pepperoni")){
			pizza=new PepperoniPizza(nyIngredientFactory);
			pizza.setName("New York Style Pepperoni Pizza");
		}
        return pizza;
	}
}

###########################################################################
public class javatest1 {
	public static void main(String[] args) throws IOException,ClassNotFoundException{
		PizzaStore nyPizzaStore=new NYPizzaStore();
		nyPizzaStore.orderPizza("cheese");
		System.out.print("\n");
		PizzaStore chicagoPizzaStore=new ChicagoPizzaStore();
		chicagoPizzaStore.orderPizza("clam");
	}
}

 

 #举个例子(python)

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-

__author__ = 'Andy'
"""
大话设计模式
设计模式——抽象工厂模式
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类
"""
import sys

#抽象用户表类
class User(object):

    def get_user(self):
        pass

    def insert_user(self):
        pass

#抽象部门表类
class Department(object):

    def get_department(self):
        pass

    def insert_department(self):
        pass


#操作具体User数据库类-Mysql
class MysqlUser(User):

    def get_user(self):
        print 'MysqlUser get User'

    def insert_user(self):
        print 'MysqlUser insert User'

#操作具体Department数据库类-Mysql
class MysqlDepartment(Department):

    def get_department(self):
        print 'MysqlDepartment get department'

    def insert_department(self):
        print 'MysqlDepartment insert department'

#操作具体User数据库-Orcal
class OrcaleUser(User):

    def get_user(self):
        print 'OrcalUser get User'

    def insert_user(self):
        print 'OrcalUser insert User'

#操作具体Department数据库类-Orcal
class OrcaleDepartment(Department):

    def get_department(self):
        print 'OrcalDepartment get department'

    def insert_department(self):
        print 'OrcalDepartment insert department'

#抽象工厂类
class AbstractFactory(object):

    def create_user(self):
        pass

    def create_department(self):
        pass

class MysqlFactory(AbstractFactory):

    def create_user(self):
        return MysqlUser()

    def create_department(self):
        return MysqlDepartment()

class OrcaleFactory(AbstractFactory):

    def create_user(self):
        return OrcalUser()

    def create_department(self):
        return OrcalDepartment()

if __name__ == "__main__":

    db = sys.argv[1]
    myfactory = ''
    if db == 'Mysql':
        myfactory = MysqlFactory()
    elif db == 'Orcal':
        myfactory = OrcaleFactory()
    else:
        print "不支持的数据库类型"
        exit(0)
    user = myfactory.create_user()
    department = myfactory.create_department()
    user.insert_user()
    user.get_user()
    department.insert_department()
    department.get_department()

 代码来自https://www.cnblogs.com/onepiece-andy/p/python-abstract-factory-pattern.html

 

#工厂方法模式与抽象工厂模式对比

)都是负责创建对象,工厂方法模式  用的方法是通过继承,抽象工厂模式 用的方法是对象的组合

)工厂方法模式 通过子类来创建对象,客户只需要知道所使用的抽象类型,右子类来负责决定具体类型。换句话说 工厂方法模式只负责将客户从具体类型中解耦。

)抽象工厂模式 用来创建一个产品家族的抽象类型,也可以把客户从所使用的具体产品中解耦。可以把一组相关的产品集合起来。

如果需要扩展这组相关产品,就必须改变接口,这是抽象工厂的缺点。工厂方法模式只涉及一个产品。

)抽象工厂模式经常使用工厂方法模式来实现它(抽象工厂模式)的具体工厂,纯粹是用来创建产品。

 

 

 

参考

《Head First设计模式》

 https://blog.csdn.net/qq_28859325/article/details/60580578

https://www.jianshu.com/p/610a26d9d958

 

posted @ 2019-10-10 15:48  筱筱的春天  阅读(2718)  评论(0编辑  收藏  举报