应用场景
创建新对象最简单的办法是使用new关键字和具体类。只有在某些场合下,创建和维护对象工厂所带来的额外复杂性才是物有所值。
工厂模式
工厂模式分为简单工厂、工厂方法模式和抽象工厂模式。
这三种模式从上到下逐步抽象,并且更具一般性。还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。下面是使用工厂模式的两种情况:
1.在编码时不能预见需要创建哪种类的实例。
2.系统不应依赖于产品类实例如何被创建、组合和表达的细节。
简单工厂模式
1.定义抽象手机产品类,定义抽象方法获取手机价格
/**
* @Description 抽象手机产品
**/
public abstract class Phone {
//获取价格
abstract void getPrice();
}
2.定义苹果手机产品和华为产品类
public class IPhone extends Phone{
@Override
public void getPrice() {
System.out.println("我的价格是:5000");
}
}
public class HuaWei extends Phone {
@Override
public void getPrice() {
System.out.println("我的价格是:4000");
}
}
3.定义手机产品抽象工厂
public class PhoneFactory {
public static Phone creatPhone(String type){
Phone phone = null;
if (type.equals("iphone")) {
phone = new IPhone();
} else if (type.equals("huawei")) {
phone = new HuaWei();
} else {
phone = new HuaWei();
}
return phone;
}
}
4.测试类方法
public class Main {
public static void main(String[] args) {
Phone phone = PhoneFactory.creatPhone("huawei");
Phone phone1 = PhoneFactory.creatPhone("iphone");
Phone phone2 = PhoneFactory.creatPhone("iphone222");
phone.getPrice();
phone1.getPrice();
phone2.getPrice();
}
}
结果:
我的价格是:4000
我的价格是:5000
我的价格是:4000
6.总结
松耦合,调用方只需与工厂类交互,无需关心实例怎么创建的。
扩展性强,只需新增一个实现类和修改工厂方法即可,这也算缺点的一方面。当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
工厂方法模式
介绍
提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一个类(产品类),并且由该实现类创建对应类的实例。
作用
1.一定程度上解耦,消费者和产品实现类隔离开,只依赖产品接口(抽象产品),产品实现类如何改动与消费者完全无关。
2.一定程度增加扩展性,若增加一个产品实现,只需要实现产品接口,修改工厂创建产品的方法,消费者可以无感知(若消费者不关心具体产品是什么的情况)。
3.一定程度增加代码的封装性、可读性。清楚的代码结构,对于消费者来说很少的代码量就可以完成很多工作。
示例
1.手机工厂接口
public interface Phone {
void getPrice();
}
2.工厂实现 ,苹果手机与华为手机
public class Iphone implements Phone {
@Override
public void getPrice() {
System.out.println("我的价格是:5000");
}
}
public class HuaWei implements Phone {
@Override
public void getPrice() {
System.out.println("我的价格是:4000");
}
}
3.测试类
public class Main {
public static void main(String[] args) {
HuaWei hw = new HuaWei();
Iphone iphone = new Iphone();
hw.getPrice();
iphone.getPrice();
}
}
结果:
我的价格是:4000
我的价格是:5000
总结
使用工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。所以我建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
抽象工厂方法
定义
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
同时满足:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品以其使用。
抽象工厂角色
这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色
它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色
它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色
具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
实例
1.创建不同抽象产品,Ipad和Phone两种
public interface IPad {
void getPrice();
}
public interface Phone {
void getPrice();
}
2.产品实现类
public class IPadMini4 implements IPad {
@Override
public void getPrice() {
System.out.println("Iphone-mini4,我的价格是:3000");
}
}
public class HwP20 implements Phone {
@Override
public void getPrice() {
System.out.println("华为P20,我的价格是:40000");
}
}
3.定义抽象工厂角色
public interface PhoneFactory {
public IPad creatPad();
public Phone creadPhone();
}
4.定义具体工厂角色
public class Factroy implements PhoneFactory {
public IPad creatPad() {
return new IPadMini4();
}
public Phone creadPhone() {
return new HwP20();
}
}
5.测试类
public class main {
public static void main(String[] args) {
PhoneFactory factroy = new Factroy();
factroy.creadPhone().getPrice();
factroy.creatPad().getPrice();
}
}
结果:
华为P20,我的价格是:40000
Iphone-mini4,我的价格是:3000
总结
优点:
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。
缺点:
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
场景:
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。也就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。