003 工厂方法模式

一 .说一说

在简单工厂之中,我们的最终演化的过程中,有一个很烦的问题就是当增加产品的时候,我们的枚举类会不断的修改.

虽然修改在一定程度上我们能保证不出问题,但这依然不够优雅.


 

二 .工厂演进

提供一个生产枪的工厂接口.

public interface GunFactory {
    Gun productGun();
}

子类:

public class AK47GunFactory implements GunFactory {
    @Override
    public Gun productGun() {
        return new AK47();
    }
}
public class B11GunFactory implements GunFactory{
    @Override
    public Gun productGun() {
        return new B11();
    }
}

客户端:

public static void main(String[] args) {
        Gun gun = new AK47GunFactory().productGun();
        gun.shot();
    }

现在我们如果要扩展枪的话,就可以扩展工厂和对应的枪了.

我们能够保证代码符合开闭原则的.


问题的出现:

每次出现新枪,客户端虽然代码不用变化,但是客户端在一定程度上需要知道自己需要什么样的枪工厂.

我们来回忆一下使用工厂的好处,就是获得创建对象时细节的控制权.

从这一点上讲,使用工厂比直接使用构造函数好.

这就是我们使用工厂最直接的原因.[可以获得创建对象细节的权利].


看下面的情景:

我需要使用枪来打鸟.

public abstract class  ShotBird {
    protected abstract Gun getGun() ;
    public void shotBird() {
        getGun().shot();
        System.out.println("鸟被打死了!!");
    }
}

现在我们需要使用ak47打鸟.

public class Ak47ShotBird extends ShotBird {
    @Override
    protected Gun getGun() {
        return new AK47();
    }
}

客户端:

public static void main(String[] args) {
        ShotBird shot = new Ak47ShotBird();
        shot.shotBird();
    }

我们每次选用不同的枪来打鸟,只需要实现以下工厂方法就好了.有了枪,怎么打鸟的代码就可以复用了.

这也就是说,我们除了创建枪的代码不能复用,其它的代码都能复用.


 

工厂方法模式:

定义定义创建对象的方法[对象--一般以接口的形式表示],让子类完成该方法.父类可以将其他代码进行复用.

也就是说,工厂方法模式创建的对象一般不是给客户端使用的,是给父类的内部代码使用的.


 

现在由一个情景:

用户的登录过程:

public abstract class Login {
    //获得一个匹配器
    protected abstract Matcher getMatcher();
    //实现登录
    public boolean login(String username , String password) {
        Matcher matcher = getMatcher();
        return matcher.check(username,password);
    }
}

现在登录的方式有很多,比如使用MD5加密之后再登录.

//匹配器
public interface Matcher {
    //通过账号和密码进行匹配
    Boolean check(String username, String password);
}
public class MD5Matcher implements Matcher {
    @Override
    public Boolean check(String username, String password) {
        System.out.println("通过账号"+username +"和密码"+password +"进行验证");
        //省略大量验证代码
        return Boolean.TRUE;
    }
}

实现一个MD5登录.

public class MD5Login extends Login {
    @Override
    protected Matcher getMatcher() {
        return new MD5Matcher();
    }
}

客户端代码:

    public static void main(String[] args) {
        Login login = new MD5Login();
        login.login("trek", "123456");
    }

通过上面的例子,我们现在应该能理解工厂方法模式了.

工厂方法模式创建的对象一般都是给内部使用的,目的是为了复用其它的代码,比如登录登录时可以记录日志啊等操作.

从这一点上讲,和简单工厂根本不是一个方向上的模式.

我看了一些资料,觉的那些资料上应该是片面的理解了这个模式.

最终我是按照淹没设计模式的方向去理解这个模式的.


 

posted @ 2018-03-18 12:41  最爱五仁月饼  阅读(169)  评论(0编辑  收藏  举报