定义一个工厂类,根据传入的参数不一样返回不一样的实例,被建立的实例具备共同的父类或接口。23种设计模式并不包括简单工厂模式,它更像一种编程习惯。编程
简单工厂模式由三部分组成:设计模式
- 工厂类(Creator)角色:担任这个角色的是简单工厂模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下建立产品对象。
- 抽象产品(AbstractProduct)角色:担任这个角色的类是由简单工厂模式所建立的对象的父类,或它们共同拥有的接口。
- 具体产品(ConcreteProduct)角色:简单工厂模式所建立的任何对象都是这个角色的实例。
1.3.1 电视机父类TVbash
public abstract class TV {
abstract void openTV();
}
复制代码
1.3.2 海尔电视机和长虹电视机分别继承TVide
public class HaierTV extends TV {
public void openTV() {
System.out.println("open haier TV");
}
}
复制代码
public class ChanghongTV extends TV {
public void openTV() {
System.out.println("open changhong TV");
}
}
复制代码
1.3.3 工厂类工具
public class Factory {
public static TV watchTV(String type) throws Exception {
if (type.equals("Haier")) {
return new HaierTV();
} else if (type.equals("Changhong")) {
return new ChanghongTV();
} else {
throw new Exception();
}
}
}
复制代码
1.3.4 客户端调用ui
public class Test {
public static void main(String[] args) throws Exception {
TV tv = Factory.watchTV("Haier");
tv.openTV();
}
}
复制代码
- 工厂类负责建立的对象比较小。
- 客户端只关心传入工厂类的参数,不关心对象的建立过程。
Calendar.class中的部分源码:spa
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;
}
复制代码
1.6.1 优势:设计
- 工厂类含有必要的判断逻辑,能够决定在何时建立哪个产品类的实例,客户端能够免除直接建立产品对象的责任,而仅仅“消费”产品;简单工厂模式经过这种作法实现了对责任的分割,它提供了专门的工具类用于建立对象。
- 客户端无须知道所建立的具体产品类的类名,只须要知道产品类所对应的参数便可,对应一些复杂的类名,经过简单工厂模式能够减小使用者的记忆量。
- 经过引入配置文件,能够在不修改任何客户端代码的状况下更换和增长新的具体产品类,在必定程度上提升了系统的灵活性。
- 当须要引入新的产品是不须要修改客户端的代码,只须要添加相应的产品类并修改工厂类就能够了,因此说从产品的角度上简单工厂模式是符合“开-闭”原则的。
1.6.2 缺点:code
- 因为工厂类集中了全部产品建立逻辑,工厂类通常被咱们称做“全能类”或者“上帝类”,由于全部的产品建立它都完成,这看似是好事,但仔细想一想是有问题的。这样一旦不能正常工做,整个系统都要受到影响。
- 系统扩展困难,一旦添加新产品就要修改工厂逻辑,在产品类型较多时,有可能形成工厂逻辑过于复杂,不利于系统的扩展和维护。因此说从工厂的角度来讲简单工厂模式是不符合“开-闭”原则的。
- 因为使用静态工厂方法,形成工厂角色没法造成基于继承的等级结构。
工厂父类负责定义建立产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样作的目的是将产品类的实例化操做延迟到工厂子类中完成,即经过工厂子类来肯定究竟应该实例化哪个具体产品类。orm
工厂方法模式由四部分组成:
- 抽象工厂(AbstractCreater)角色:担任这个角色的是工厂方法模式的核心,与调用者直接交互用来提供产品。任何在模式中建立对象的工厂类必须继承或者实现这个接口。
- 具体工厂(ConcreteCreator)角色:担任这个角色的是实现了抽象工厂接口的具体实现类。具体工厂角色含有与应用密切相关的逻辑,而且受到应用程序的调用以建立产品对象。
- 抽象产品(AbstractProduct)角色:工厂方法模式所建立的对象的超类。主要目的是定义产品的规范,全部的产品实现都必须遵循这些规范。
- 具体产品(ConcreteProduct)角色:实现了抽象产品角色所声明的接口,工厂方法所建立的每个对象都是某个具体产品角色的实例。
2.3.1 电视机父类TV
public abstract class TV {
abstract void openTV();
}
复制代码
2.3.2 海尔电视机和长虹电视机分别继承TV
public class HaierTV extends TV {
public void openTV() {
System.out.println("open haier TV");
}
}
复制代码
public class Changhong extends TV {
public void openTV() {
System.out.println('open changhong TV');
}
}
复制代码
2.3.3 抽象工厂类
public abstract class Factory {
public abstract TV watchTV();
}
复制代码
2.3.4 具体工厂类
public class HaierFactory extends Factory {
public TV watchTV() {
return new HaierTV();
}
}
复制代码
public class ChanghongFactory extends Factory {
public TV watchTV() {
return new ChanghongTV();
}
}
复制代码
2.3.5 客户端调用
public class Test {
public static void main(String[] args) throws Exception {
Factory factory = new HaierFactory();
TV tv = factory.watchTV();
tv.openTV();
}
}
复制代码
- 客户端不须要知道它所场景的对象的类,只须要知道建立具体产品的工厂类。
- 客户端能够经过子类来指定建立对应的对象。
- 工厂方法用来建立客户所须要的产品,同时还向客户隐藏了哪一种具体产品类将被实例化这一细节,用户只须要关心所需产品对应的工厂,无须关心建立细节。
- 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它可以使工厂能够自主肯定建立何种产品对象,而如何建立这个对象的细节则彻底封装在具体工厂内部。
- 在系统加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其余的具体工厂和具体产品。这样系统的可扩展性变得良好,彻底符合“开-闭“原则。
提供一个建立一系列相关或相互依赖对象的接口,而无须指明它们具体的类。
- 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,取子类有海尔电视机、长虹电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构。
- 产品族:在抽象工厂模式中,产品族是指同一个工厂生产的,位于不一样产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
抽象工厂模式和工厂方法模式相似都是四部分组成的,不一样的是,抽象工厂模式中具体工厂再也不是只建立一种产品,一个具体的工厂能够建立一个产品族的产品。
3.4.1 电视机父类TV
public abstract class TV {
abstract void openTV();
}
复制代码
3.4.2 海尔电视机和长虹电视机分别继承TV
public class HaireTV extends TV {
public void openTV() {
System.out.println("open haire TV");
}
}
复制代码
public class ChanghongTV extends TV {
public void openTV() {
System.out.println('open changhong TV');
}
}
复制代码
3.4.3 冰箱父类Refrigerator
public abstract class Refrigerator {
abstract void openRefrigerator();
}
复制代码
3.4.4 海尔冰箱和长虹冰箱分别继承Refrigerator
public class HaierRefrigerator extends Refrigerator {
public void openRefrigerator() {
System.out.println("open haier refrigerator");
}
}
复制代码
public class ChanghongRefrigerator extends Refrigerator {
public void openRefrigerator() {
System.out.println("open changhong refrigerator");
}
}
复制代码
3.4.5 抽象工厂类,定义同一族产品的两个不一样等级结构的产品结构
public abstract class Factory {
public abstract TV watchTV();
public abstract Refrigerator takeThings();
}
复制代码
3.4.6 具体工厂类
public class HaierFactory extends Factory {
public TV watchTV() {
return new HaierTV();
}
public Refrigerator takeThings() {
return new HaierRefrigerator();
}
}
复制代码
public class ChanghongFactory extends Factory {
public TV watchTV() {
return new ChanghongTV();
}
public Refrigerator takeThings() {
return new ChanghongRefrigerator();
}
}
复制代码
3.4.7 客户端调用
public class Test {
public static void main(String[] args) throws Exception {
Factory factory = new HaierFactory();
TV tv = factory.watchTV();
tv.openTV();
Refrigerator refrigerator = factory.takeThings();
refrigerator.openRefrigerator();
}
}
复制代码
- 一个系统不该当依赖于产品类实例如何被建立、组合和表达的细节,这对于全部形态的工厂模式都是重要的。
- 系统的产品有多于一个的产品族,而系统只消费群体某一族的产品。
- 同属于同一产品族的产品是在一块儿使用的,这一约束必须在系统的设计中体现出来。 *系统提供一个产品类的库,全部的产品以一样的接口出现,从而使客户端不依赖与实现。
3.6.1 优势
- 抽象工厂模式隔离了具体类的生成,使得客户不须要知道什么被建立。因为这种隔离,更换一个具体工厂就变得相对容易。全部的具体工厂都实现了抽象工厂中定义的那些公共接口,所以只需改变具体工厂的实例,就能够在某种程序上改变整个系统的行为。另外,应用抽象工厂模式能够实现高内聚低耦合的设计目的。
- 当一个产品族中的多个对象被设计成一块儿工做时,它可以保证客户端始终只使用同一个产品族中的对象。这对一些须要根据当前环境来决定其行为的软件系统来讲,是一种很是使用的设计模式。
- 增长新的具体工厂和产品族很方便,无须改动其余,符合“开闭”原则。
3.6.2 缺点
- 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是由于在抽象工厂角色中规定了全部可能被场景的产品集合,要支持新种类的产品就意味着要对接口进行扩展,而这将涉及到对抽象工厂角色及其全部子类的修改,显然带来较大的不便。
- 开闭原则的倾斜性(增长新的工厂和产品族容易,增长新的产品等级结构麻烦)。
特别声明:一、如若文中有错之处,欢迎大神指出。 二、文章是参考网上一些大神的文章,本身整理出来的,如如有侵权,可联系我删除。