前言:除了使用new操作符之外,还有更多制造对象的方法。你将会了解到实例化这个活动不应该总是公开地进行,也会认识到初始化经常造成“耦合”问题。
当使用“new” 时,的确是在实例化一个具体类,所以用的确实是实现,而不是接口。具体的类会导致代码更脆弱,更缺乏弹性。
使用接口编程,让代码具有弹性,但是还是得要具体类的实例
Duck duck = new MallardDuck();
当有一群相关的具体类时,通常会写出这样的代码:
Duck duck;
if(picnic){
duck = new MrllardDuck();
}else if(hunting){
duck = new DecoyDuck();
}else if(inBathTub){
duck = new RubberDuck();
}
当看到这样的代码,一旦有变化或者扩展,就必须重新打开这段代码进行检查和修改。通常这样修改过的代码将造成部分系统更难维护和更新,而且也更容易犯错。
"new"有什么不对?
在技术上,new没有错,毕竟这是Java的基础部分,真正的犯人是“改变”,以及它是如何影响new的使用的。
使用接口编程。可以隔离掉以后系统可能发生的一大堆改变。为什么呢?如果代码是针对接口而写的,那么通过多态,它可以与任何新类实现该接口。但是,当代码使用大量的具体类时,等于是自找麻烦,因为一旦加入新的具体类,就必须修改代码。也就是说,你的代码并非“对修改关闭”。想用新的具体类型来扩展代码,必须重新打开它。
一、简单工厂
简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。
根据不同类型,预订不同的Pizza,可能大部分人会这么写:
/**
* 根据Pizza类型,实例化正确的具体类,然后将其赋值给pizza变量
* 请注意,这里任何Pizza都必须实现Pizza接口
*
* @param type Pizza类型
*/
public Pizza orderPizza(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 PeperoniPizza();
}
pizza.prepare();//准备
pizza.bake();//烘焙
pizza.cut();//切片
pizza.box();//装盒
return pizza;
}
但是压力来自于增加更多的Pizza类型,ClamPizza(蛤蜊Pizza)、VeggiePizza(素食Pizza),所以你得要往上述代码中加入这些具体的类型,也可能因为某些Pizza卖的不好而淘汰,这时,你又得要往上述代码中,去掉某些具体的Pizza。
很明显,如果实例化“某些”具体类,将使orderPizza()出问题,而且也无法让orderPizza()对修改关闭;但是现在我们已经知道哪些会改变,哪些不会改变。
简单工厂
应用简单工厂封装Pizza的创建,由SimplePizzaFactory专职创建Pizza。
/**
* 描述:简单工厂
* 程序狗: Xander
* 创建日期: 2018/07/05 21:05
*/
public class SimplePizzaFactory {
/**
* 所有客户使用这个方法来实例化新对象
*
* @param type
* @return
*/
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 PeperoniPizza();
}
return pizza;
}
}
重做PizzaStore类
public class PizzaStore {
private SimplePizzaFactory mSimplePizzaFactory;
public PizzaStore(SimplePizzaFactory simplePizzaFactory) {
mSimplePizzaFactory = simplePizzaFactory;
}
/**
* 根据Pizza类型,实例化正确的具体类,然后将其赋值给pizza变量
* 请注意,这里任何Pizza都必须实现Pizza接口
*
* @param type Pizza类型
*/
public Pizza orderPizza(String type) {
Pizza pizza = mSimplePizzaFactory.createPizza(type);
pizza.prepare();//准备
pizza.bake();//烘焙
pizza.cut();//切片
pizza.box();//装盒
return pizza;
}
}
二、工厂方法模式
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
需求
Pizza店经营又成,有一些地区的Pizza店想要加盟。其中一家加盟店希望工厂能制造纽约风味的Pizza:薄饼、美味的酱料和少量的芝士;另一家加盟店希望工厂能制造芝加哥风味的Pizza,他们的顾客想要厚饼、重味的酱料和大量的芝士。
简单工厂方案
NYPizzaFactory nyFactory = new NYPizzaFactory();//这里创建的工厂,是制造纽约风味的Pizza。
PizzaStore nyStore = new PizzaStore(nyFactory );
nyStore.orderPizza("Veggie");
//芝加哥Pizza店也类似
ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();//这里创建的工厂,是制造芝加哥风味的Pizza。
PizzaStore chicagoStore = new PizzaStore(chicagoFactory );
chicagoStore.orderPizza("Veggie");
ChicagoPizzaFactory代码
/**
* 描述:简单工厂——芝加哥风味
* 程序狗: Xander
* 创建日期: 2018/07/05 21:05
*/
public class ChicagoPizzaFactory {
private ChicagoPizzaFactory() {
}
public static ChicagoPizzaFactory newInstance() {
ChicagoPizzaFactory instance = new ChicagoPizzaFactory();
return instance;
}
/**
* 所有客户使用这个方法来实例化新对象
*
* @param type
* @return
*/
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new ChicagoCheesePizza();
} else if (type.equals("greek")) {
pizza = new ChicagoGreekPizza();
} else if (type.equals("pepperoni")) {
pizza = new ChicagoPeperoniPizza();
}
return pizza;
}
}
NYPizzaFactory代码
/**
* 描述:简单工厂——纽约风味
* 程序狗: Xander
* 创建日期: 2018/07/05 21:05
*/
public class NYPizzaFactory {
private NYPizzaFactory() {
}
public static NYPizzaFactory newInstance() {
NYPizzaFactory instance = new NYPizzaFactory();
return instance;
}
/**
* 所有客户使用这个方法来实例化新对象
*
* @param type
* @return
*/
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new NYCheesePizza();
} else if (type.equals("greek")) {
pizza = new NYGreekPizza();
} else if (type.equals("pepperoni")) {
pizza = new NYPeperoniPizza();
}
return pizza;
}
}
质量控制
各个加盟店虽然使用了简单工厂创建Pizza。但是PizzaStore,都是由他们自己控制,所以他们可以采用其自创的流程:烘烤的做法有些差异、不要切片、使用其他厂商的盒子。
所以我们想让Pizza的制作活动局限于PizzaStore类,而同时又能让这些加盟店可以自由地制作该区域的风味。所要做的事情,就是把createPizza()方法放回到PizzaStore中,不过要把它设置成“抽象方法”,然后为每个区域风味创建一个PizzaStore的子类。
PizzaStore转变,原本是由一个对象负责所有具体类的实例化,现在变成由一群子类来负责实例化。
PizzaStore代码:
public abstract class PizzaStore {
/**
* 根据Pizza类型,实例化正确的具体类,然后将其赋值给pizza变量
* 请注意,这里任何Pizza都必须实现Pizza接口
*
* @param type Pizza类型
*/
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
pizza.prepare();//准备
pizza.bake();//烘焙
pizza.cut();//切片
pizza.box();//装盒
return pizza;
}
/**
* 创建Pizza的工厂方法
*
* @param type
* @return
*/
public abstract Pizza createPizza(String type);
}
NYStylePizzaStore 代码:
/**
* 描述:纽约风味的Pizza店
* 程序狗: Xander
* 创建日期: 2018/07/06 12:59
*/
public class NYStylePizzaStore extends PizzaStore{
@Override
public Pizza createPizza(String type) {
NYPizzaFactory nyPizzaFactory = NYPizzaFactory.newInstance();
Pizza pizza = nyPizzaFactory.createPizza(type);
return pizza;
}
}
ChicagoStylePizzaStore 代码
/**
* 描述:芝加哥风味的Pizza店
* 程序狗: Xander
* 创建日期: 2018/07/06 12:59
*/
public class ChicagoStylePizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
ChicagoPizzaFactory chicagoPizzaFactory = ChicagoPizzaFactory.newInstance();
Pizza pizza = chicagoPizzaFactory.createPizza(type);
return pizza;
}
}
工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。
认识工厂方法模式
所有工厂模式都用来封装对象的创建。工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。
组成元素
创建者(Creator)类
如PizzaStore类,这是抽象创建者类,它定义了一个工厂方法,让子类实现此方法,制造产品。创建者通常会包含依赖于抽象产品的代码,而这些抽象产品由子类制造。创建者不需要真的知道在制造哪种具体的产品。
产品类
工厂生产产品,对PizzaStore类来说,产品就是Pizza。
简单工厂和工厂方法之间的差异
简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是一个创建框架,让子类去决定要如何实现。
三、设计原则六——依赖倒置原则
要依赖抽象,不要依赖具体类。
这个原则说明了:不能让高层组件依赖底层组件,而且,不管高层或者底层组件,“两者”都应该依赖于抽象。
所谓“高层”组件,是由其他底层组件定义其行为的类。例如,PizzaStore是个高层组件,因为它的行为是由Pizza定义的,PizzaStore创建所有不同的Pizza对象,准备、烘焙、切片、装盒,而此Pizza本身属于底层组件。
如上诉案例,应用工厂方法后:
在应用工厂方法之后,你将注意到,高层组件(也就是PizzaStore)和底层组件(也就是这些Pizza)都依赖了Pizza抽象。想要遵循依赖倒置原则,工厂方法并非是唯一的技巧,但却是最具有威力的技巧之一。
下面的指导方针,能帮你避免在OO设计中违反依赖倒置原则:
- 变量不可以持有具体类的引用。
如果使用new,就回持有具体类的引用。你可以改用工厂来避免这样的做法。 - 不要让类派生自具体类。如果派生自具体类,你就会依赖具体类,请派生自一个抽象(接口或者抽象类)。
- 不要覆盖基类中已实现的方法。如果覆盖基类中已实现的方法,那么你的基类就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有的子类共享。
但是正如同我们的许多原则一样,应尽量达到这个原则,而不是随时都要遵循这个原则。因为任何java程序都有违反这些知道方针的地方!
另一方面,如果有个类可能改变,你可以采用一些好技巧(例如工厂方法)来封装改变。
四、抽象工厂模式
抽象工厂模式 提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类。
需求
现在,我们要建造一个工厂来生产原料;这个工厂将负责创建原料家族中 的每一种原料。也就是说,工厂需要生产面团、酱料、芝士等。
但是各个区域需要的原料都存在差异,比如:
芝加哥Pizza菜单
- 芝士Pizza:番茄酱料、意大利白干酪、Parmesan干酪、Pizza草
- 素食Pizza:番茄酱料、意大利白干酪、Parmesan干酪、茄子、菠菜、黑橄榄
- 蛤蜊Pizza:番茄酱料、意大利白干酪、Parmesan干酪、蛤蜊
- 意大利腊肠Pizza:番茄酱料、意大利白干酪、Parmesan干酪、茄子、菠菜、黑橄榄、意式腊肠
纽约的Pizza菜单
- 芝士Pizza:大蒜番茄酱料、Reggiano干酪、大蒜
- 素食Pizza:大蒜番茄酱料、Reggiano干酪、蘑菇洋葱、红椒
- 蛤蜊Pizza:大蒜番茄酱料、Reggiano干酪、新鲜蛤蜊
- 意式腊肠Pizza:大蒜番茄酱料、Reggiano干酪、蘑菇、洋葱、红椒、意式腊肠。
应用抽象工厂模式
①将原料工厂定义为一个接口 PizzaIngredientFactory ,这个接口负责创建所有的原料。
/**
* 描述:原料工厂接口
* 程序狗: Xander
* 创建日期: 2018/7/9 7:14
*/
public interface PizzaIngredientFactory {
/**
* 创建面团
*
* @return
*/
Dough createDough();
/**
* 创建酱料
*
* @return
*/
Sauce createSauce();
/**
* 创建奶酪
*
* @return
*/
Cheesex createCheese();
/**
* 创建蔬菜
*
* @return
*/
Veggies[] createVeggies();
/**
* 创建 意式腊肠
*
* @return
*/
Pepperoni createPepperoni();
/**
* 创建蛤蜊
*
* @return
*/
Clams createClams();
}
2、为每个区域建造一个工厂。你需要创建一个继承自 PizzaIngredientFactory的子类来实现每一个创建方法。
纽约原料工厂 NYPizzaIngredientFactory
/**
* 描述:纽约原料工厂
* 程序狗: Xander
* 创建日期: 2018/07/09 07:25
*/
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Dough createDough() {
return new ThinCrustDough();
}
@Override
public Sauce createSauce() {
return new MarinaraSauce();
}
@Override
public Cheesex createCheese() {
return new ReggiannoCheese();
}
@Override
public Veggies[] createVeggies() {
Veggies veggies[] = {new Garlic(),new Onion(),new Mushroom(),new RedPepper()};
return veggies;
}
@Override
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
@Override
public Clams createClams() {
return new FreshClams();
}
}
芝加哥原料工厂 ChicagoPizzaIngredientFactory
/**
* 描述:芝加哥原料工厂
* 程序狗: Xander
* 创建日期: 2018/07/09 07:25
*/
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Dough createDough() {
return new ThickCrustDough();
}
@Override
public Sauce createSauce() {
return new PlumTomatoSauce();
}
@Override
public Cheesex createCheese() {
return new MozzarellaCheese();
}
@Override
public Veggies[] createVeggies() {
Veggies veggies[] = {new BlackOlives(),new Spinach(),new Eggplant()};
return veggies;
}
@Override
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
@Override
public Clams createClams() {
return new FrozenClams();
}
}
重写 Pizza
/**
* 描述:Pizza基类
* 程序狗: Xander
* 创建日期: 2018/07/05 13:52
*/
public abstract class Pizza {
protected String mName;//名称
protected Dough mDough;//面团
protected Sauce mSauce;//酱料
protected Veggies mVeggies[];//蔬菜
protected Cheese mCheese;//奶酪
protected Pepperoni mPepperoni;// 意式腊肠
protected Clams mClams;//蛤蜊
protected List mToppings = new ArrayList<>();//佐料
protected PizzaIngredientFactory mPizzaIngredientFactory;//原料工厂
public Pizza(PizzaIngredientFactory pizzaIngredientFactory) {
mPizzaIngredientFactory = pizzaIngredientFactory;
}
public void bake() {
System.out.println("Bake for 25 minutes at 350");
}
public void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}
public void box() {
System.out.println("Place pizza in official PizzaStore box");
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public Dough getDough() {
return mDough;
}
public void setDough(Dough dough) {
mDough = dough;
}
public Sauce getSauce() {
return mSauce;
}
public void setSauce(Sauce sauce) {
mSauce = sauce;
}
public Cheese getCheese() {
return mCheese;
}
public void setCheese(Cheese cheese) {
mCheese = cheese;
}
public List getToppings() {
return mToppings;
}
public void setToppings(List toppings) {
mToppings = toppings;
}
public abstract void prepare();
public Veggies[] getVeggies() {
return mVeggies;
}
public void setVeggies(Veggies[] veggies) {
mVeggies = veggies;
}
public Pepperoni getPepperoni() {
return mPepperoni;
}
public void setPepperoni(Pepperoni pepperoni) {
mPepperoni = pepperoni;
}
public Clams getClams() {
return mClams;
}
public void setClams(Clams clams) {
mClams = clams;
}
public PizzaIngredientFactory getPizzaIngredientFactory() {
return mPizzaIngredientFactory;
}
public void setPizzaIngredientFactory(PizzaIngredientFactory pizzaIngredientFactory) {
mPizzaIngredientFactory = pizzaIngredientFactory;
}
@Override
public String toString() {
return "Pizza{" +
"mName='" + mName + '\'' +
", mDough=" + mDough +
", mSauce=" + mSauce +
", mVeggies=" + Arrays.toString(mVeggies) +
", mCheese=" + mCheese +
", mPepperoni=" + mPepperoni +
", mClams=" + mClams +
", mToppings=" + mToppings +
", mPizzaIngredientFactory=" + mPizzaIngredientFactory +
'}';
}
}
芝士Pizza CheesePizza
/**
* 描述:芝士Pizza
* 程序狗: Xander
* 创建日期: 2018/07/05 20:50
*/
public class CheesePizza extends Pizza {
public CheesePizza(PizzaIngredientFactory pizzaIngredientFactory) {
super(pizzaIngredientFactory);
}
@Override
public void prepare() {
this.mDough = this.mPizzaIngredientFactory.createDough();
this.mSauce = this.mPizzaIngredientFactory.createSauce();
this.mCheese = this.mPizzaIngredientFactory.createCheese();
}
}
蛤蜊Pizza ClamPizza
/**
* 描述:蛤蜊Pizza
* 程序狗: Xander
* 创建日期: 2018/07/09 07:47
*/
public class ClamPizza extends Pizza {
public ClamPizza(PizzaIngredientFactory pizzaIngredientFactory) {
super(pizzaIngredientFactory);
}
@Override
public void prepare() {
this.mDough = this.mPizzaIngredientFactory.createDough();
this.mSauce = this.mPizzaIngredientFactory.createSauce();
this.mCheese = this.mPizzaIngredientFactory.createCheese();
this.mClams = this.mPizzaIngredientFactory.createClams();
}
}
重写NYPizzaFactory , 简单工厂——纽约风味Pizza
/**
* 描述:简单工厂——纽约风味Pizza
* 程序狗: Xander
* 创建日期: 2018/07/05 21:05
*/
public class NYPizzaFactory {
protected PizzaIngredientFactory mPizzaIngredientFactory;//原料工厂
private NYPizzaFactory(PizzaIngredientFactory pizzaIngredientFactory) {
this.mPizzaIngredientFactory = pizzaIngredientFactory;
}
public static NYPizzaFactory newInstance(PizzaIngredientFactory pizzaIngredientFactory) {
NYPizzaFactory instance = new NYPizzaFactory(pizzaIngredientFactory);
return instance;
}
/**
* 所有客户使用这个方法来实例化新对象
*
* @param type
* @return
*/
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new NYCheesePizza(mPizzaIngredientFactory);
} else if (type.equals("greek")) {
pizza = new NYGreekPizza(mPizzaIngredientFactory);
} else if (type.equals("pepperoni")) {
pizza = new NYPeperoniPizza(mPizzaIngredientFactory);
}
return pizza;
}
}
重写ChicagoPizzaFactory , 简单工厂——芝加哥风味Pizza
/**
* 描述:简单工厂——芝加哥风味Pizza
* 程序狗: Xander
* 创建日期: 2018/07/05 21:05
*/
public class ChicagoPizzaFactory {
protected PizzaIngredientFactory mPizzaIngredientFactory;//原料工厂
private ChicagoPizzaFactory(PizzaIngredientFactory pizzaIngredientFactory) {
this.mPizzaIngredientFactory = pizzaIngredientFactory;
}
public static ChicagoPizzaFactory newInstance(PizzaIngredientFactory pizzaIngredientFactory) {
ChicagoPizzaFactory instance = new ChicagoPizzaFactory(pizzaIngredientFactory);
return instance;
}
/**
* 所有客户使用这个方法来实例化新对象
*
* @param type
* @return
*/
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new ChicagoCheesePizza(mPizzaIngredientFactory);
} else if (type.equals("greek")) {
pizza = new ChicagoGreekPizza(mPizzaIngredientFactory);
} else if (type.equals("pepperoni")) {
pizza = new ChicagoPeperoniPizza(mPizzaIngredientFactory);
}
return pizza;
}
}
重写 NYStylePizzaStore, 纽约风味的Pizza店
/**
* 描述:纽约风味的Pizza店
* 程序狗: Xander
* 创建日期: 2018/07/06 12:59
*/
public class NYStylePizzaStore extends PizzaStore{
@Override
public Pizza createPizza(String type) {
PizzaIngredientFactory pizzaIngredientFactory = new NYPizzaIngredientFactory();
NYPizzaFactory nyPizzaFactory = NYPizzaFactory.newInstance(pizzaIngredientFactory);
Pizza pizza = nyPizzaFactory.createPizza(type);
return pizza;
}
}
重写 ChicagoStylePizzaStore, 芝加哥风味的Pizza店
/**
* 描述:芝加哥风味的Pizza店
* 程序狗: Xander
* 创建日期: 2018/07/06 12:59
*/
public class ChicagoStylePizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
PizzaIngredientFactory pizzaIngredientFactory = new ChicagoPizzaIngredientFactory();
ChicagoPizzaFactory chicagoPizzaFactory = ChicagoPizzaFactory.newInstance(pizzaIngredientFactory);
Pizza pizza = chicagoPizzaFactory.createPizza(type);
return pizza;
}
}
测试类——预定Pizza
/**
* 描述:测试类——预定Pizza
* 程序狗: Xander
* 创建日期: 2018/07/09 08:02
*/
public class OrderPizzaTest {
public static void main(String args[]) {
// 预定一个 纽约风味的 Cheese Pizza
NYStylePizzaStore nyStylePizzaStore = new NYStylePizzaStore();
nyStylePizzaStore.orderPizza("cheese");
}
}
抽象工厂和工厂方法的应用比较
- 抽象工厂,当你需要创建产品家族和想让制造的相关产品集合起来时,可以使用抽象工厂模式;
- 工厂方法,当你需要把你当客户代码从需要实例化的具体类中解耦,或者如果你目前还不确定将来需要实例化哪些具体类时,可以使用工厂模式。
要点
- 所有的工厂都是用来封装对象的创建;
- 简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类中解耦;
- 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象;
- 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中;
- 所有工厂模式都通过减少具体应用程序和具体类之间的依赖促进松耦合;
- 工厂方法允许类将实例化延迟到子类进行;
- 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类;
- 依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象;
- 工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体编程。
感谢你的耐心阅读,工厂模式基本知识和应用就介绍到这里了。
最后回顾一下
我们的设计工具箱中的工具
1、OO基础
① 抽象
② 封装
③ 多态
④ 继承
2、OO原则
① 封装变化
② 多用组合,少用继承
③ 针对接口编程,不针对实现编程
④ 为交互对象之间的松耦合设计而努力
⑤ 类应该对扩展开放,对修改关闭
⑥ 依赖抽象,不要依赖具体编程
3、OO模式
① 策略模式——定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
② 观察者模式——在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会受到通知并自动更新。
③ 装饰者模式——动态地将责任附加到对象上,若要扩展功能,装饰者提供有别于继承的另一种选择。
④ 工厂方法模式——定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
抽象工厂模式——提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
感谢阅读!
No.3 装饰者模式(Decorator)
No.2 观察者模式(Observer)
No.1 策略模式(Strategy)
前言 为何要使用设计模式
Demo代码