簡單工廠模式
簡介
- 簡單工廠模式屬于創(chuàng)建型模式,是工廠模式中的一種.簡單工廠模式是由一個工廠對象決定創(chuàng)建出哪一個產(chǎn)品類的實例 簡單工廠模式是工廠模式家族中最簡單實用的模式
- 簡單工廠模式:定義了一個創(chuàng)建對象的類,由這個類口來封裝實例化對象的行為(代碼)
- 在軟件開發(fā)中,當(dāng)我們會大量的創(chuàng)建某種,某類或者某批對象的時候,就會使用到工廠模式
為何使用簡單工廠模式 舉個例子 制作披薩的例子
//將Pizza 類做成抽象
public abstract class Pizza {
protected String name; //名字
//準備原材料, 不同的披薩不一樣,因此稠鼻,我們做成抽象方法
public abstract void prepare();
public void bake() {
System.out.println(name + " baking;");
}
public void cut() {
System.out.println(name + " cutting;");
}
//打包
public void box() {
System.out.println(name + " boxing;");
}
public void setName(String name) {
this.name = name;
}
}
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println(" 給制作奶酪披薩 準備原材料 ");
}
}
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println(" 給希臘披薩 準備原材料 ");
}
}
public class OrderPizza {
//構(gòu)造器
public OrderPizza() {
Pizza pizza = null;
String orderType; // 訂購披薩的類型
do {
orderType = getType();
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希臘披薩 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披薩 ");
} else {
break;
}
//輸出pizza 制作過程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
// 寫一個方法腰埂,可以獲取客戶希望訂購的披薩種類
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 種類:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
//相當(dāng)于一個客戶端矫夷,發(fā)出訂購
public class PizzaStore {
public static void main(String[] args) {
// TODO Auto-generated method stub
//new OrderPizza();
}
}
測試:
input pizza 種類:
greek
給希臘披薩 準備原材料
希臘披薩 baking;
希臘披薩 cutting;
希臘披薩 boxing;
input pizza 種類:
假如此時再增加一個 披薩 的種類 需要繼續(xù)修改很多代碼
public class PepperPizza extends Pizza {
@Override
public void prepare() {
System.out.println(" 給胡椒披薩準備原材料 ");
}
}
public class OrderPizza {
//構(gòu)造器
public OrderPizza() {
Pizza pizza = null;
String orderType; // 訂購披薩的類型
do {
orderType = getType();
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希臘披薩 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披薩 ");
} else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披薩");
} else {
break;
}
//輸出pizza 制作過程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
// 寫一個方法漱受,可以獲取客戶希望訂購的披薩種類
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 種類:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
怎么修改 使用簡單工廠類
代碼
//簡單工廠類
public class SimpleFactory {
//更加orderType 返回對應(yīng)的Pizza 對象
public Pizza createPizza(String orderType) {
Pizza pizza = null;
System.out.println("使用簡單工廠模式");
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希臘披薩 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披薩 ");
} else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披薩");
}
return pizza;
}
修改代碼
public class OrderPizza {
//定義一個簡單工廠對象
SimpleFactory simpleFactory;
Pizza pizza = null;
//構(gòu)造器
public OrderPizza(SimpleFactory simpleFactory) {
setFactory(simpleFactory);
}
public void setFactory(SimpleFactory simpleFactory) {
String orderType = ""; //用戶輸入的
this.simpleFactory = simpleFactory; //設(shè)置簡單工廠對象
do {
orderType = getType();
pizza = this.simpleFactory.createPizza(orderType);
//輸出pizza
if(pizza != null) { //訂購成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println(" 訂購披薩失敗 ");
break;
}
}while(true);
}
// 寫一個方法返顺,可以獲取客戶希望訂購的披薩種類
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 種類:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
測試類
//相當(dāng)于一個客戶端肥隆,發(fā)出訂購
public class PizzaStore {
public static void main(String[] args) {
// TODO Auto-generated method stub
// new OrderPizza();
//使用簡單工廠模式
new OrderPizza(new SimpleFactory());
System.out.println("~~退出程序~~");
}
}
測試結(jié)果
input pizza 種類:
greek
使用簡單工廠模式
給希臘披薩 準備原材料
希臘披薩 baking;
希臘披薩 cutting;
希臘披薩 boxing;
input pizza 種類:
使用簡單工廠模式
訂購披薩失敗
~~退出程序~~
這樣修改之后,以后需要修改,就只需要修改 工廠類和需要添加的類 而生產(chǎn)披薩就不用再修改代碼
簡單工廠也叫做靜態(tài)工廠模式
代碼
//簡單工廠類
public class SimpleFactory {
//更加orderType 返回對應(yīng)的Pizza 對象
public Pizza createPizza(String orderType) {
Pizza pizza = null;
System.out.println("使用簡單工廠模式");
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希臘披薩 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披薩 ");
} else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披薩");
}
return pizza;
}
//簡單工廠模式 也叫 靜態(tài)工廠模式
public static Pizza createPizza2(String orderType) {
Pizza pizza = null;
System.out.println("使用簡單工廠模式2");
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希臘披薩 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披薩 ");
} else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披薩");
}
return pizza;
}
}
這樣再調(diào)用的時候就可以通過類名調(diào)用了
public class OrderPizza2 {
Pizza pizza = null;
String orderType = "";
// 構(gòu)造器
public OrderPizza2() {
do {
orderType = getType();
pizza = SimpleFactory.createPizza2(orderType);
// 輸出pizza
if (pizza != null) { // 訂購成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println(" 訂購披薩失敗 ");
break;
}
} while (true);
}
// 寫一個方法,可以獲取客戶希望訂購的披薩種類
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 種類:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
//相當(dāng)于一個客戶端,發(fā)出訂購
public class PizzaStore {
public static void main(String[] args) {
// TODO Auto-generated method stub
// new OrderPizza();
//使用簡單工廠模式
// new OrderPizza(new SimpleFactory());
// System.out.println("~~退出程序~~");
new OrderPizza2();
}
}
輸出測試
input pizza 種類:
greek
使用簡單工廠模式2
給希臘披薩 準備原材料
希臘披薩 baking;
希臘披薩 cutting;
希臘披薩 boxing;
input pizza 種類:
qw
使用簡單工廠模式2
訂購披薩失敗
工廠方法模式
簡介
工廠方法模式設(shè)計方案:將披薩項目的實例化功能抽象成抽象方法,在不同的口味點餐子類中具體實現(xiàn)
工廠方法模式:定義了一個創(chuàng)建對象的抽象方法.由子類決定實例化的類.工廠模式方法把對象的實例化推遲到子類
需求:客戶在點披薩的時候,可以點不同口味的披薩,比如 北京的奶酪披薩.北京的胡椒披薩,或者是倫敦的胡椒披薩
思路1
使用簡單工廠模式,創(chuàng)建不同的工廠類,比如 BJSimpleFactory 或者 LDSimpleFactory等.但是不易于維護,可拓展性不好
思路2
使用工廠方法模式
創(chuàng)建以上的方法
/將Pizza 類做成抽象
public abstract class Pizza {
protected String name; //名字
//準備原材料, 不同的披薩不一樣搀绣,因此飞袋,我們做成抽象方法
public abstract void prepare();
public void bake() {
System.out.println(name + " baking;");
}
public void cut() {
System.out.println(name + " cutting;");
}
//打包
public void box() {
System.out.println(name + " boxing;");
}
public void setName(String name) {
this.name = name;
}
}
public class BJCheesePizza extends Pizza{
@Override
public void prepare() {
setName("北京奶酪披薩");
System.out.println("北京奶酪披薩 準備原材料");
}
}
public class BJPepperPizza extends Pizza {
@Override
public void prepare() {
setName("北京胡椒披薩");
System.out.println("北京胡椒披薩 準備原材料");
}
}
public class LDCheesePizza extends Pizza{
@Override
public void prepare() {
setName("倫敦奶酪披薩");
System.out.println("倫敦奶酪披薩 準備原材料");
}
}
public class LDPepperPizza extends Pizza {
@Override
public void prepare() {
setName("倫敦胡椒披薩");
System.out.println("倫敦胡椒披薩 準備原材料");
}
}
public abstract class OrderPizza {
//定義一個抽象方法 createPizza 讓各個工廠子類自己實現(xiàn)
abstract Pizza createPizza(String orderType);
//構(gòu)造器
public OrderPizza() {
Pizza pizza = null;
String orderType; // 訂購披薩的類型
do {
orderType = getType();
pizza = createPizza(orderType); //抽象
//輸出pizza 制作過程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
// 寫一個方法,可以獲取客戶希望訂購的披薩種類
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 種類:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
public class LDOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new LDCheesePizza();
}else if(orderType.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
public class BJOrderPizza extends OrderPizza{
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new BJCheesePizza();
}else if(orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
return pizza;
}
}
測試
public class PizzaStore {
public static void main(String[] args) {
//創(chuàng)建北京口味的披薩
new BJOrderPizza();
// new LDOrderPizza();
}
}
測試結(jié)果
input pizza 種類:
cheese
北京奶酪披薩 準備原材料
北京奶酪披薩 baking;
北京奶酪披薩 cutting;
北京奶酪披薩 boxing;
input pizza 種類:
pepper
北京胡椒披薩 準備原材料
北京胡椒披薩 baking;
北京胡椒披薩 cutting;
北京胡椒披薩 boxing;
input pizza 種類:
input pizza 種類:
cheese
倫敦奶酪披薩 準備原材料
倫敦奶酪披薩 baking;
倫敦奶酪披薩 cutting;
倫敦奶酪披薩 boxing;
input pizza 種類:
pepper
倫敦胡椒披薩 準備原材料
倫敦胡椒披薩 baking;
倫敦胡椒披薩 cutting;
倫敦胡椒披薩 boxing;
input pizza 種類:
抽象工廠模式
簡介
1.抽象工廠模式:定義了一個 interface 用于創(chuàng)建相關(guān)或有依賴關(guān)系的對象簇 而無需指明具體的類
2.抽象工廠模式可以將簡單工廠模式和工廠方法模式進行整合
3.從設(shè)計層上看,抽象工廠模式就是對簡單工廠模式的改進(或者是進一步的抽象)
4.將工廠模式抽象成兩層:AbsFactory(抽象工廠)和具體的實現(xiàn)工廠子類,程序員可以根據(jù)創(chuàng)建的對象類型使用對應(yīng)的工廠子類.這樣將單個的簡單工廠類變成了 工廠簇,更利于代碼的維護和拓展
繼續(xù)修改上一個披薩案例
其中
BJCheesePizza.java
BJPepperPizza.java
LDCheesePizza.java
LDPepperPizza.java
Pizza.java
沒有修改
//是一個抽象工廠模式的接口
public interface AbsFactory {
//讓下面的工廠子類 來具體實現(xiàn)
public Pizza createFactory(String orderType);
}
public class BJFactory implements AbsFactory{
@Override
public Pizza createFactory(String orderType) {
System.out.println("使用的是抽象方法創(chuàng)建");
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new BJCheesePizza();
}else if(orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
return pizza;
}
}
public class LDFactory implements AbsFactory{
@Override
public Pizza createFactory(String orderType) {
System.out.println("使用的是抽象方法創(chuàng)建");
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new LDCheesePizza();
}else if(orderType.equals("pepper")) {
pizza = new LDPepperPizza
();
}
return pizza;
}
}
public class OrderPizza {
AbsFactory absFactory;
public OrderPizza(AbsFactory factory) {
setFactory(factory);
}
private void setFactory(AbsFactory factory) {
Pizza pizza = null;
String orderType = "";// 用戶輸入
this.absFactory = factory;
do {
orderType = getType();
// factory可能是北京的工廠子類,也可能是倫敦的工廠子類
pizza = factory.createFactory(orderType);
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("訂購失敗");
break;
}
} while (true);
}
// 寫一個方法链患,可以獲取客戶希望訂購的披薩種類
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 種類:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
測試
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza(new BJFactory());
// new OrderPizza(new BJFactory());
}
}
打印結(jié)果
input pizza 種類:
pepper
使用的是抽象方法創(chuàng)建
北京胡椒披薩 準備原材料
北京胡椒披薩 baking;
北京胡椒披薩 cutting;
北京胡椒披薩 boxing;
input pizza 種類:
cheese
使用的是抽象方法創(chuàng)建
北京奶酪披薩 準備原材料
北京奶酪披薩 baking;
北京奶酪披薩 cutting;
北京奶酪披薩 boxing;
input pizza 種類:
input pizza 種類:
pepper
使用的是抽象方法創(chuàng)建
北京胡椒披薩 準備原材料
北京胡椒披薩 baking;
北京胡椒披薩 cutting;
北京胡椒披薩 boxing;
input pizza 種類:
cheese
使用的是抽象方法創(chuàng)建
北京奶酪披薩 準備原材料
北京奶酪披薩 baking;
北京奶酪披薩 cutting;
北京奶酪披薩 boxing;
input pizza 種類:
工廠模式在 JDK-Calendar應(yīng)用的源碼分析
JDK的Calendar類,就是使用了簡單工廠模式
public class Factory {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
System.out.println(cal.get(Calendar.YEAR));
System.out.println(cal.get(Calendar.MONTH)+1);
System.out.println(cal.get(Calendar.DAY_OF_MONTH));
System.out.println(cal.get(Calendar.DAY_OF_YEAR));
System.out.println(cal.get(Calendar.MINUTE));
System.out.println(cal.get(Calendar.SECOND));
}
}
public static Calendar getInstance(){
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
工廠模式的小結(jié)
1.工廠模式的意義
將實例化對象的代碼提取出來,放到一個類中統(tǒng)一管理和維護,達到和主項目的依賴關(guān)系的解耦,從而提升項目的拓展和維護性
2.三種工廠模式
3.設(shè)計模式的依賴抽象原則
a.創(chuàng)建對象的時候,不要直接new一個類,而是把這個new類的動作放在一個工廠的方法中,并返回.有的書上說,變量不要直接持有具體類的引用
b.不要讓類繼承具體類,而是繼承抽象類或者是實現(xiàn) interface 接口
c.不要覆蓋基類中已經(jīng)實現(xiàn)的方法