以房地产举例,简单工厂模式如下:
(文章大多解释在代码注释中,不可忽略!)
interface Realty{ //房地产接口
void sell(); //出售行为
}
//此接口相当于抽象概括房地产整个行业,由内部方法描述房地产行业的内部各种细节。
//以此达到可扩展的目的,例如租赁等行为都将在这个接口中展开;
class Employee implements Realty{ //员工实现类
@Override
public void sell() {
System.out.println("员工主动出售");
}
}
class HouseOwner implements Realty{ //房主实现类
@Override
public void sell() {
System.out.println("房主寻求出售");
}
}
以上两个角色都具有售卖行为,可以实现房地产接口,达到共同管理。
需要实现他们,可以使用简单工厂模式,如下:
class RealtyFactory{ //命名规范:需要以Factory结尾,增强可读性。
private RealtyFactory(){}
public static Realty provider(String realtyType){ //对外暴露api,强调一点:返回值为Realty,使用多态特性,达到引用扩大化,多态是工厂模式核心。
return getInstant(realtyType);
}
private static Realty getInstant(String realtyType){ //将主体逻辑封装,层次清晰,防止代码冗余。
if (StringUtils.isEmpty(realtyType)) return null;
if ("employee".equalsIgnoreCase(realtyType)){
return new Employee();
}else if ("role".equalsIgnoreCase(realtyType)){
return new HouseOwner();
}else return null;
}
}
测试类:
public class PatternTest {
public static void main(String[] args) {
Realty employee = RealtyFactory.provider("employee"); //传入实体类名字,由工厂返回实例化。
if (!ObjectUtils.isEmpty(employee)) employee.sell();
}
}
测试结果:
抽象工厂模式:
在讲抽象工厂模式之前,需要对RealtyFactory进行改造,达到不修改源码情况下,简单工厂和抽象工厂并用效果。
class RealtyFactory{ //房地产工厂
public Realty withInstance(String realtyType){ //增加非静态化方法,具体原因将从下文展开。
return getInstant(realtyType);
}
public static Realty provider(String realtyType){
return getInstant(realtyType);
}
private static Realty getInstant(String realtyType){
if (StringUtils.isEmpty(realtyType)) return null;
if ("employee".equalsIgnoreCase(realtyType)){
return new Employee();
}else if ("role".equalsIgnoreCase(realtyType)){
return new HouseOwner();
}else return null;
}
}
abstract class RegionAbstractFactory{
public abstract RealtyFactory getRealtyFactory();
}
//房地产行业有地区划分,可以将房地产工厂汇总,构成抽象类,由这个抽象工厂管理所有房地产工厂;
//扩展一点,日常工作中,在功能未定的情况下,我们可以将方法声明为抽象预留出来。
class TangShanCity extends RegionAbstractFactory{
@Override
public RealtyFactory getRealtyFactory() {
return new RealtyFactory(); //增加非静态化方法的原因在此,如果还有其它城市的话,都需要使用对象调用创建工厂方法。
}
public TangShanCity() { //这个无参构造只是为了便于观察代码行为。
System.out.println("唐山地区房地产");
}
}
//唐山城市的房地产
由于城市的增加,需要为城市创建一个工厂的提供者,由他们实例化具体工厂:
class FactoryProvider {
private FactoryProvider() {
}
public static RegionAbstractFactory getFactory(String factoryType) { //对外暴露api
return getInstance(factoryType);
}
private static RegionAbstractFactory getInstance(String factoryType) { //核心逻辑封装成私有方法
if (StringUtils.isEmpty(factoryType)) return null;
if ("tangshanCity".equalsIgnoreCase(factoryType)) {
return new TangshanCity();
} else return null;
}
}
测试方法:
public class PatternTest {
public static void main(String[] args) {
RegionAbstractFactory tangshan = FactoryProvider.getFactory("tangshanCity");
Assert.notNull(tangshan, "参数错误");
RealtyFactory realtyFactory = tangshan.getRealtyFactory();
Realty employee = realtyFactory.withInstance("employee");
employee.sell();
}
}
测试结果:
工厂方法模式:
interface RealtyFactory{
Region getFactory(String regionName); //预留工厂
}
class TangshanFactory implements RealtyFactory{ //具体工厂
@Override
public Region getFactory() {
return new TangshanCity();
}
}
以上两个工厂毫无关联,在拓展时,也仅需要实现工厂接口即可,而不需要修改源码。
class BaodingFactory implements RealtyFactory{ //具体工厂
@Override
public Region getFactory() {
return new BaodingCity();
}
}
abstract class Region{ //地区抽象类:抽取地区共有的方法进行约束,有助于横向拓展。
private String name;
public abstract void getName(); //预留行为
}
class TangshanCity extends Region{ //一个城市继承地区抽象类。
@Override
public void getName() {
System.out.println("Tangshan");
}
}
class BaodingCity extends Region{ //一个城市继承地区抽象类。
@Override
public void getName() {
System.out.println("保定");
}
}
测试类:
class Test{
public static void main(String[] args) {
Factory factory = new Factory();
Region tangshanCity = factory.getFactory("tangshanCity");
tangshanCity.getName();
}
}
工厂方法模式对工厂和地区同时约束,好处在于:在有新的城市或新的工厂需要加入时,不需要修改源码,即可达到共同行为约束的目的,减少修改代码带来的风险。