创建型设计模式之手工打造、简单工厂、工厂方法和抽象工厂(新)

1 手工打造

  我们先利用时光机回退到大概二十年前:你需要一部手机给你在远方的女朋友打电话。但是,你没有手机啊,市面上也没有卖的啊,可是相思之情难以抑制,每当傍晚都会涌上心头。于是,你开始自己造手机。

public class HWMobile{
    public HWMobile() {
        System.out.println("自己动手生产一部华为手机,好累啊");
    }

    public void call(String number) {
        System.out.println("利用华为手机拨打电话:"+number);
    }

    public void sendMessage(String message) {
        System.out.println("利用华为手机发送短信:"+message);
    }
}

  我们自己制造了一部华为手机,虽然颜值不高,但是可以打电话,发短信了!

public class Test {
    public static void main(String[] args) {
        HWMobile hwMobile=new HWMobile();
        hwMobile.call("95279527");
        hwMobile.sendMessage("I miss you");
    }
}

  二话不说,拿起手机给妹子打电话,泡妹的事业又可以继续了;但是累啊!自己动手一点一滴地生产组装一个手机,累得直吐血啊!
  怎么办呢?有没有其他工厂来帮我们生产手机呢?有啊,必须有啊,比如全球最大的代工厂穷士康!

2 简单工厂模式(Simple Factory)

  好了,既然有工厂,那我们就请工厂代劳。

public interface Mobile {
    public void call(String number);
    public void sendMessage(String message);
}

//标配版手机
class HWStandardMobile implements Mobile {
    public HWStandardMobile() {
        System.out.println("工厂生产了一部标配版华为手机");
    }

    @Override
    public void call(String number) {
        System.out.println("利用华为手机拨打电话:"+number);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("利用华为手机发送短信:"+message);
    }
}

//高配版手机
class HWProfessionalMobile implements Mobile {
    public HWProfessionalMobile() {
        System.out.println("工厂生产了一部高配版华为手机");
    }

    @Override
    public void call(String number) {
        System.out.println("利用华为手机拨打电话:"+number);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("利用华为手机发送短信:"+message);
    }
}

  穷士康说:既然要造手机,我就给你造两个,一个高配版,一个标准版,想用哪个自己挑就是了。好嘞,我们来看看工厂是怎么制造手机的:

public class MobileFactory {
    public final static String STANDARE="standard";
    public final static String PROFESSIONAL="professional";
    public static Mobile createMobile(String type) {
        Mobile mobile = null;
        switch (type) {
            case STANDARE:
                mobile=new HWStandardMobile();
                break;
            case PROFESSIONAL:
                mobile=new HWProfessionalMobile();
                break;
            default:
                break;
        }
        return mobile;
    }
}

  只要我们告诉工厂生产什么手机,它就会自动帮我们制造。而且,工厂会根据CPU的不同自动区分是建造标准版的手机还是高配版的手机。既然这么方便,那就赶紧试一把:

public class Test {
    public static void main(String[] args) {
        MobileFactory.createMobile("standard");
        MobileFactory.createMobile("professional");
    }
}

  在此,让工厂生产两部手机,一部高配,一部标配!这样是不是省事好多?爽了吧?是的,你是爽了,舒服了;可是,工厂不愿意了!为啥呢?假设哪天你不愿意用标配和高配的手机了,你想用更高级的钻石级华为手机,那么这个工厂就得进行大的改动:

switch (type) {
            case STANDARE:
                mobile=new HWStandardMobile();
                break;
            case PROFESSIONAL:
                mobile=new HWProfessionalMobile();
                break;
            default:
                break;
    }

  更加确切地说:这个switch语句得新加case了!为了生成新系列的手机就得对工厂进行伤筋动骨的改造,人家穷士康当然不愿意了!再从软件工程的角度来看,这也违背了开闭原则。所以,简单工厂模式并不是真正的设计模式,23种设计模式里并没有它的一席之地。

3 工厂方法模式(Factory Method)

  虽然全球最大的代工厂穷士康不愿意为了新产品大刀阔斧地改造原来的工厂但是也不愿意订单花落他家;生意还是要做,钱还是要赚的。那怎么办?干脆建立一个工厂模型,每当有新产品的制造需求时按照这个模型新建一个工厂就行啦!

public interface Mobile {
    public void call(String number);
    public void sendMessage(String message);
}

//标配版手机
class HWStandardMobile implements Mobile {
    public HWStandardMobile() {
        System.out.println("工厂生产了一部标配版华为手机");
    }

    @Override
    public void call(String number) {
        System.out.println("利用华为手机拨打电话:"+number);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("利用华为手机发送短信:"+message);
    }
}

//高配版手机
class HWProfessionalMobile implements Mobile {
    public HWProfessionalMobile() {
        System.out.println("工厂生产了一部高配版华为手机");
    }

    @Override
    public void call(String number) {
        System.out.println("利用华为手机拨打电话:"+number);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("利用华为手机发送短信:"+message);
    }
}

  手机还是原来的两部,没有变化;但是工厂和之前不一样了,我们来瞅瞅:

//抽象的手机工厂
public interface MobileFactory {
    public abstract Mobile createMobile();
}

//生成华为标配手机的工厂
class HWStandardMobileFactory implements MobileFactory {
    @Override
    public Mobile createMobile() {
        HWStandardMobile mobile=new HWStandardMobile();
        return mobile;
    }
}

//生成华为高配手机的工厂
class HWProfessionalMobileFactory implements MobileFactory {
    @Override
    public Mobile createMobile() {
        HWProfessionalMobile mobile=new HWProfessionalMobile();
        return mobile;
    }

}

  先创立了一个抽象工厂,然后建立一个生产工厂标配版的华为手机,再专门建立一个工厂生产高配版本的手机。如果有新的华为手机(例如比高配版还要牛气的钻石系列)的生产需求,那么再建立一个对应的工厂就行啦!
  工厂方法模式小结(该方式是符合开闭原则的):

  • 具体产品均实现了自抽象产品接口。 比如,高配版和标准版的华为手机都implements Mobile
  • 具体工厂均实现了抽象工厂接口。 比如,生产标配手机的工厂和生产高配手机的工厂都implements MobileFactory
  • 当有新产品需求时,只需要新建工厂进行生产,而不必去修改原来的已经存在的工厂代码。
    好了,我们来利用工厂方法模式生产手机吧:
public class Test {
    public static void main(String[] args) {
        MobileFactory mobileFactory=null;
        mobileFactory=new HWStandardMobileFactory();
        mobileFactory.createMobile();
        mobileFactory=new HWProfessionalMobileFactory();
        mobileFactory.createMobile();
    }
}

  但是与简单工厂模式比起来,工厂方法模式虽然遵守了开闭原则,但是建立了很多具体的工厂类。这样的代码有些臃肿,不便于维护。可以在在工厂这方面做做文章,争取一个工厂就可以生产所有的手机。那么,该怎么优化呢?请继续往下看。
  对于手机,我们不做改变;它与之前一样没有任何变化。

//抽象的手机工厂
public interface MobileAbstractFactory {
    public <T extends Mobile> T createMobile(Class<T> clazz);
}

  抽象的手机工厂和以往不大一样,最大的差异就是此处使用了泛型。

//具体的手机工厂
public class MobileConcreteFactory implements MobileAbstractFactory {
    @Override
    public <T extends Mobile> T createMobile(Class<T> clazz) {
        Mobile mobile=null;
        String className=clazz.getName();
        try {
             mobile=(Mobile) Class.forName(className).newInstance();
        }catch(Exception e) {
            e.printStackTrace();
        }
        return (T) mobile;
    }
}

  这是具体的手机工厂的核心代码。在该具体工厂中采用反射的方式生产不同的手机;从而避免建立众多的工厂。好了,来测试一下:

public class Test {
    public static void main(String[] args) {
        MobileAbstractFactory mobileFactory=new MobileConcreteFactory();
        mobileFactory.createMobile(HWStandardMobile.class);
        mobileFactory.createMobile(HWProfessionalMobile.class);
    }
}

  哇哈,我们只用创建一个工厂就可以生产不同的手机!想生产说明手机直接告诉厂商手机类型就行啦!穷士康也高兴坏了,真爽,节约了一大笔资金!

4 抽象工厂模式(Abstract Factory)

  华为手机上市一段时间之后,用户普遍反应:日常生活中的不小心导致手机经常摔坏!穷士康听到这个消息后,就开始琢磨了:给手机配备手机保护套!也就是说:为高配版的手机生产与之对应的真皮保护套;至于标配版的手机就整个塑料材质的保护套。毕竟是生意人啊,想得真细致,太精打细算了!

public interface Mobile {
    public void call(String number);
    public void sendMessage(String message);
}

//标配版手机
class HWStandardMobile implements Mobile {
    public HWStandardMobile() {
        System.out.println("工厂生产了一部标配版华为手机");
    }

    @Override
    public void call(String number) {
        System.out.println("利用华为手机拨打电话:"+number);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("利用华为手机发送短信:"+message);
    }
}

//高配版手机
class HWProfessionalMobile implements Mobile {
    public HWProfessionalMobile() {
        System.out.println("工厂生产了一部高配版华为手机");
    }

    @Override
    public void call(String number) {
        System.out.println("利用华为手机拨打电话:"+number);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("利用华为手机发送短信:"+message);
    }
}

  这是手机,与之前一模一样。

public interface PhoneCase {
    public abstract void protectMobile();
}

//用于保护标准版手机的保护套
class HWStandardPhoneCase implements PhoneCase{
    public HWStandardPhoneCase() {
        System.out.println("工厂生产StandardPhoneCase用于保护标准版的华为手机");
    }

    @Override
    public void protectMobile() {
        System.out.println("HWStandardPhoneCase protectMobile()");
    }
}

//用于保护高配版手机的保护套
class HWProfessionalPhoneCase implements PhoneCase{
    public HWProfessionalPhoneCase() {
        System.out.println("工厂生产ProfessionalPhoneCase用于保护高配版的华为手机");
    }

    @Override
    public void protectMobile() {
        System.out.println("HWProfessionalPhoneCase protectMobile()");
    }
}

  这是为手机配备的保护套用于不同配置的华为手机。

//抽象的手机工厂
public interface MobileAbstractFactory {
    public abstract Mobile createMobile();
    public abstract PhoneCase createPhoneCase();
}

  抽象工厂除了制造手机,还要制造手机保护套。

//具体的手机工厂
public class StandardMobileConcreteFactory implements MobileAbstractFactory {
    @Override
    public Mobile createMobile() {
        Mobile mobile=new HWStandardMobile();
        return mobile;
    }

    @Override
    public PhoneCase createPhoneCase() {
        PhoneCase phoneCase=new HWStandardPhoneCase();
        return phoneCase;
    }
}

  该具体的工厂负责生产标配的手机及其保护套。

//具体的手机工厂
public class ProfessionalMobileConcreteFactory implements MobileAbstractFactory {
    @Override
    public Mobile createMobile() {
        Mobile mobile=new HWProfessionalMobile();
        return mobile;
    }

    @Override
    public PhoneCase createPhoneCase() {
        PhoneCase phoneCase=new HWProfessionalPhoneCase();
        return phoneCase;
    }
}

  该具体的工厂负责生产高配的手机及其保护套。

public class Test {
    public static void main(String[] args) {
        MobileAbstractFactory mobileFactory=null;
        mobileFactory=new StandardMobileConcreteFactory();
        mobileFactory.createMobile();
        mobileFactory.createPhoneCase();

        mobileFactory=new ProfessionalMobileConcreteFactory();
        mobileFactory.createMobile();
        mobileFactory.createPhoneCase();
    }
}

  要生产不同的手机及其与之匹配的保护套只需要建立不同的工厂就行啦;至于工厂怎么生产的细节问题就不用管了,而且工厂生产出来的手机和保护套必然是相互匹配的,不会出现错误的搭配!

  到了这里,我想不少人都有疑问了:这不和工厂方法模式基本完全一样么?无非是工厂里多了一个方法而已!从我们的代码也可以看出来:ProfessionalMobileConcreteFactory生成出来的比如是高配手机和高配的手机保护套,绝对不会乱套!再来看抽象工厂模式的定义:抽象工厂模式为创建一组相关或相互依赖的对象提供一个接口!“相关或相互依赖的对象”?不就是我们这里的手机和与之对应的手机保护套。所以说:抽象工厂模式和工厂方法模式的区别就在于需要创建的对象的复杂程度上。而且,在简单工厂模式,工厂方法模式,抽象工厂模式中这三者中抽象工厂模式是最为抽象、最具一般性的。

5 转载链接

从手工打造到工厂设计模式的演变历程

猜你喜欢

转载自blog.csdn.net/chenliguan/article/details/78896729
今日推荐