十一回了趟老家,十一前工作一大堆忙成了狗,十一回來后又積累了一大堆又 忙成了狗,今天剛好抽了一點空開始寫工廠方法模式
我看了《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
