概念理解
工廠模式是一種創(chuàng)建型模式,統(tǒng)一創(chuàng)建對象饮六,供客戶端使用其垄。客戶端僅需從工廠中取對象卤橄,而不用關(guān)心創(chuàng)建對象的邏輯绿满。
實例描述
以西餐廳制作披薩為例,西餐廳目前提供披薩種類有cheese pizza,pepper pizza,bacon pizza窟扑,點餐系統(tǒng)需要根據(jù)客戶要求不同喇颁,制作不同的pizza。
直接實現(xiàn):
在不使用任何模式的情況下嚎货,類的結(jié)構(gòu)大致是這樣的
public abstract class Pizza {
private String name ;
public Pizza(String name){
this.name = name;
}
public abstract void prepare();
public void bake(){
System.out.println(name+" is baked");
}
public void cut(){
System.out.println(name+" is cut");
}
public void box(){
System.out.println(name+" is boxed");
}
public String getName() {
return name;
}
}
public class BaconPizza extends Pizza {
public BaconPizza(){
super("baconPizza");
}
@Override
public void prepare() {
System.out.println(getName()+"is prepared");
}
}
public class RestaurantClient {
public void createPizza(String type){
Pizza pizza = null;
if("cheese".equals(type)){
pizza = new CheesePizza();
}else if ("bacon".equals(type)){
pizza=new BaconPizza();
}else if("pepper".equals(type)){
pizza=new PepperPizza();
}
if(pizza !=null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
}
缺點:這種直接的結(jié)構(gòu)是客戶端以if else的方式創(chuàng)建不同類橘霎,客戶端必須關(guān)注類是如何創(chuàng)建的,如果新加入一個新的品種殖属,客戶端需要重新改造代碼姐叁,加入新的品種。這種緊耦合的方式洗显,違背了開放封閉原則外潜。
設(shè)計一:簡單工廠模式
簡單工廠模式僅僅是把變化的部分獨立出來,客戶端僅需要關(guān)注業(yè)務(wù)挠唆,無需關(guān)注對象是如何創(chuàng)建的处窥。
public class PizzaFactory {
public static Pizza createPizza(String type){
Pizza pizza = null;
if("cheese".equals(type)){
pizza = new CheesePizza();
}else if ("bacon".equals(type)){
pizza=new BaconPizza();
}else if("pepper".equals(type)){
pizza=new PepperPizza();
}
return pizza;
}
}
public class RestaurantClient {
public void productPizza(String type){
Pizza pizza = PizzaFactory.createPizza(type);
if(pizza !=null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
}
優(yōu)點:將創(chuàng)建對象的功能獨立出來,客戶端僅需關(guān)注業(yè)務(wù)玄组,無需關(guān)注對象的創(chuàng)建邏輯
缺點:工廠類中包含了所有類的創(chuàng)建滔驾,違反了高內(nèi)聚的單一職責(zé)原則,不利于擴展俄讹。
設(shè)計二:工廠方法模式
避免簡單工廠模式的缺點哆致,核心工廠抽象為一個接口,將對象實例化交給具體工廠子類患膛,核心工廠僅給出創(chuàng)建必須實現(xiàn)的接口沽瞭,不再關(guān)注對象的具體實例化邏輯。具體工廠各司其職,給出具體的創(chuàng)建對象邏輯驹溃。
public interface IPizzaFactory {
Pizza createPizza();
}
public class BaconPizzaFactory implements IPizzaFactory {
@Override
public Pizza createPizza() {
return new BaconPizza();
}
}
public class RestaurantClient {
public void createPizza(String type){
IPizzaFactory factory =null;
if("cheese".equals(type)){
factory = new CheesePizzaFactory();
}else if ("bacon".equals(type)){
factory=new BaconPizzaFactory();
}else if("pepper".equals(type)){
factory=new PepperPizzaFactory();
}
Pizza pizza = factory.createPizza();
if(pizza !=null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
}
設(shè)計三
當(dāng)西餐廳加入了新的產(chǎn)品類別-飲料時,就用到了抽象工廠模式延曙。抽象工廠管理了多個品類的抽象創(chuàng)建方法豌鹤,同時設(shè)計一個工廠構(gòu)造器來創(chuàng)建具體的工廠。
public interface IFactory {
Pizza createPizza();
Drink createDrink();
}
public class BaconFactory implements IFactory{
@Override
public Pizza createPizza() {
return new BaconPizza();
}
@Override
public Drink createDrink() {
return new OrangeDrink();
}
}
public class FactoryCreator {
public static IFactory createFactory(String type){
IFactory factory = null;
if("cheese".equals(type)){
factory = new CheeseFactory();
}else if ("bacon".equals(type)){
factory=new BaconFactory();
}else if("pepper".equals(type)){
factory=new PepperFactory();
}
return factory;
}
}
public class RestaurantClient {
public void createPizza(String type){
IFactory factory =FactoryCreator.createFactory(type);
Pizza pizza = factory.createPizza();
if(pizza !=null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
Drink drink = factory.createDrink();
if(drink!=null){
drink.prepare();
drink.box();
}
}
}
注意點
曾經(jīng)對工廠方法模式和抽象工廠模式的概念理解模糊不清枝缔,這里記錄一下:
工廠方法模式是抽象工廠模式一個特例布疙。
工廠方法模式適用于單一品類的工廠實例創(chuàng)建,抽象工廠適用于多種品類的工廠實例創(chuàng)建愿卸,兩種適用場景不同
可以通過反射來構(gòu)造不同的工廠對象灵临,這樣擴展時不要修改工廠構(gòu)造器,改造后實例如下
public static IFactory createFactory(Class<? extends IFactory> clazz) throws IllegalAccessException, InstantiationException {
if(clazz !=null){
IFactory factory =clazz.newInstance();
return factory;
}
return null;
}
具體實例參見:https://github.com/jxl198/designPattern/tree/master/factory