南宁定制网站制作价格,做好产品策划的重要性,设计官网和推广的公司,怎么看别人网站是怎么做的绪论 shiro是一个简单易用#xff0c;功能强大的Java安全框架#xff0c;学习其源码设计思想对我们的编码水平的提高大有裨益。现在#xff0c;就从源码角度带大家学习一下shiro里面的工厂方法模式。 这里的前提是读者有过使用shiro的基础#xff0c;没有也行#xff0c;关…绪论 shiro是一个简单易用功能强大的Java安全框架学习其源码设计思想对我们的编码水平的提高大有裨益。现在就从源码角度带大家学习一下shiro里面的工厂方法模式。 这里的前提是读者有过使用shiro的基础没有也行关键理解思想就可以了。 从一个简单例子说起 首先我们先从一个简单的例子说起。我们在使用ini文件来作为用户角色权限配置的时候我们获取SecurityManager的方法是 FactorySecurityManager factory new IniSecurityManagerFactory(classpath:demo01_getstarted.ini); SecurityManager securityManager factory.getInstance();复制代码上面两行代码看似简单其实框架底层就使用了工厂方法模式。 关于上面的例子就不多讲了。这里是侧重分析工厂方法设计模式。 工厂方法模式 在工厂方法模式中我们对模式角色划分为四种 1、抽象产品产品接口比如上面shiro实例中的SecurityManager 2、具体产品比如实现了SecurityManager的类 3、抽象工厂工厂接口比如上面shiro实例中的Factory、AbstractFactory 4、具体工厂比如上面shiro实例中的IniSecurityManagerFactory 我们先来看看shiro里面工厂方法模式实现的源码 一、顶级工厂抽象接口Factory所有抽象工厂类都继承此接口 public interface FactoryT { T getInstance();}复制代码二、抽象工厂类这个抽象工厂类负责获取工厂实例具体创建过程由其子类来实现 public abstract class AbstractFactoryT implements FactoryT { private boolean singleton; private T singletonInstance; public AbstractFactory() { this.singleton true; } public boolean isSingleton() { return singleton; } public void setSingleton(boolean singleton) { this.singleton singleton; } // 获取工厂实例可以以单例形式获取也可以每一次获取都创建一个实例 public T getInstance() { T instance; if (isSingleton()) { if (this.singletonInstance null) { this.singletonInstance createInstance(); } instance this.singletonInstance; } else { instance createInstance(); } if (instance null) { String msg Factory createInstance implementation returned a null object.; throw new IllegalStateException(msg); } return instance; } protected abstract T createInstance();}复制代码上面两个工厂类抽象了最基本的工厂接口--创建工厂、获取工厂。如果我们需要对工厂类进行扩展的话只需要继承AbstractFactory来实现即可非常方便。现在看一下AbstractFactory的一个子类。 IniFactorySupport是一个特定的抽象工厂类是根据ini文件来创建工厂实例的工厂抽象类。我们不需要细究IniFactorySupport代码干了什么。只需要明白它是对根据ini文件创建工厂做了一些逻辑处理就好了。 我们可以看到继承AbstractFactory我们可以随便扩展定制我们工厂类的行为。 public abstract class IniFactorySupportT extends AbstractFactoryT { public static final String DEFAULT_INI_RESOURCE_PATH classpath:shiro.ini; private static transient final Logger log LoggerFactory.getLogger(IniFactorySupport.class); private Ini ini; private MapString, ? defaultBeans; protected IniFactorySupport() { } protected IniFactorySupport(Ini ini) { this.ini ini; } public Ini getIni() { return ini; } public void setIni(Ini ini) { this.ini ini; } protected MapString, ? getDefaults() { return defaultBeans; } public void setDefaults(MapString, ? defaultBeans) { this.defaultBeans defaultBeans; } public static Ini loadDefaultClassPathIni() { Ini ini null; if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) { log.debug(Found shiro.ini at the root of the classpath.); ini new Ini(); ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH); if (CollectionUtils.isEmpty(ini)) { log.warn(shiro.ini found at the root of the classpath, but it did not contain any data.); } } return ini; } protected Ini resolveIni() { Ini ini getIni(); if (CollectionUtils.isEmpty(ini)) { log.debug(Null or empty Ini instance. Falling back to the default {} file., DEFAULT_INI_RESOURCE_PATH); ini loadDefaultClassPathIni(); } return ini; } public T createInstance() { Ini ini resolveIni(); T instance; if (CollectionUtils.isEmpty(ini)) { log.debug(No populated Ini available. Creating a default instance.); instance createDefaultInstance(); if (instance null) { String msg getClass().getName() implementation did not return a default instance in the event of a null/empty Ini configuration. This is required to support the Factory interface. Please check your implementation.; throw new IllegalStateException(msg); } } else { log.debug(Creating instance from Ini [ ini ]); instance createInstance(ini); if (instance null) { String msg getClass().getName() implementation did not return a constructed instance from the createInstance(Ini) method implementation.; throw new IllegalStateException(msg); } } return instance; } protected abstract T createInstance(Ini ini); protected abstract T createDefaultInstance();}复制代码通过看类关系图IniSecurityManagerFactory继承IniFactorySupport在IniFactorySupport基础上面进一步封装创建工厂过程。 IniSecurityManagerFactory的源码就不贴出来了明白设计思想就可以了。 通过源码分析我们可以看到首先抽象出最基本的工厂接口具体的工厂类由其子类去实现。一个具体工厂类对应这一类产品。当需要新增产品类的时候我们只需要新加工厂类并且新增对应的产品类即可不需要修改原有工厂类代码符合了设计模式中的开闭原则、单一职责原则。 demo实现 一、创建工厂接口IFactory IFactory.java /** * 泛型代表的是产品类型 * * author wunanliang * date 2018/1/8 * since 1.0.0 */public interface IFactoryT { /** * 获取产品 * * return 产品实例 */ T getInstance();}复制代码进一步抽象工厂接口 AbstractFactory.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public abstract class AbstractFactoryT implements IFactoryT { /** * 创建产品具体创建过程由其子类实现 * * return 创建的产品实例 */ protected abstract T createInstance(); Override public T getInstance() { return createInstance(); }}复制代码二、创建产品接口 IProduct.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public interface IProduct {}复制代码进一步分类产品创建一类产品接口 Car.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public abstract class Car implements IProduct { /** * 创建汽车产品 * * return 创建的汽车产品 */ protected abstract Car createCar(); /** * 驾驶汽车 */ public abstract void drive();}复制代码具体产品类 Taxi.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public class Taxi extends Car { private Taxi taxi; Override protected Car createCar() { this.taxi new Taxi(); return this.taxi; } Override public void drive() { System.out.println(我是接送客的车); }}复制代码三、创建具体产品的工厂类 TaxtFactory.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public class TaxiFactory extends AbstractFactoryCar { Override protected Car createInstance() { return new Taxi(); }}复制代码四、客户端代码 Client.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public class Clent { public static void main(String[] args) { IFactoryCar factory new TaxiFactory(); Car taxi factory.getInstance(); taxi.drive(); }}复制代码通过例子我们知道在工厂方法模式中有一个顶级的产品接口对产品作出做基本的抽象然后产品下面还有不同产品的分类在同一类产品中又有不同的具体产品比如car类产品下面又会有多种汽车产品。每一个具体的产品都有对应一个具体的工厂类。 如果想再新加一个新的产品不论是car类产品还是非car类产品我们都可以通过新加工厂类和产品类来实现比如新增一个船类产品 Ship.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public abstract class Ship implements IProduct { /** * 造船 * * return */ protected abstract IProduct createShip(); public abstract void doSomething();}复制代码创建渔船 FishShip.java /** * 渔船 * * author wunanliang * date 2018/1/8 * since 1.0.0 */public class FishShip extends Ship { private FishShip ship; Override public IProduct createShip() { this.ship new FishShip(); return this.ship; } Override public void doSomething() { System.out.println(我在打鱼呀); }}复制代码创建渔船工厂类 FishShipFactory.java /** * author wunanliang * date 2018/1/8 * since 1.0.0 */public class FishShipFactory extends AbstractFactoryShip { Override protected Ship createInstance() { return new FishShip(); }复制代码添加一个产品我们就得添加产品类和工厂类。对于系统的扩展来说工厂方法模式有优势但是会增加系统的复杂度以及类的数量。 结束语 对于设计模式大家重点是理解这样设计的原理与优缺点不要机械的背诵条条框框。实际我们在开发真实系统时会糅合多种设计模式在一起。只有我们对设计模式有本质性的认识和掌握才是真正掌握了设计模式。