Spring 5 设计模式 - Creational

16 篇文章 0 订阅
7 篇文章 0 订阅

我们都知道怎么创建一个新对象:

    Account account = new Account();

有时候,这样写不太合适,因为这样硬编码,导致以后不容易修改对象。使用creational设计模式可以提高创建对象的灵活性。

Factory

Factory设计模式也叫Factory method设计模式。使用该模式,你可以得到对象,而且还没有暴露底层逻辑。它使用一个通用的接口或者抽象类给调用者分配对象,这样就隐藏了实现逻辑。通过工厂模式,调用者可以方便地增加、管理和销毁对象。
工厂模式带来的好处:

  • 通过使用接口,促进了松耦合
  • 可以在运行时得到实现了接口的对象
  • 对象生存期由工厂管理

Spring的工厂模式

Spring使用工厂模式实现Spring容器。Spring容器基于工厂模式增加bean,也管理每个bean的生存期。BeanFactory和ApplicationContext是工厂接口,Spring有很多实现类。

简单的例子

Factory

有两个类SavingAccount和CurrentAccount都实现了Account接口。所以,你可以增加一个工厂类,其中的一个方法可以接受一个或者多个参数返回Account类型。这个方法就是工厂方法。根据传入工厂方法的参数,可以选择要实例化的子类:

public interface Account {
    void accountType();
}

public class SavingAccount implements Account{
    @Override
    public void accountType() {
        System.out.println("SAVING ACCOUNT");
    }
}

public class CurrentAccount implements Account {
    @Override
    public void accountType() {
        System.out.println("CURRENT ACCOUNT");
    }
}

可以这样实现工厂类:

public class AccountFactory {
    final String CURRENT_ACCOUNT = "CURRENT";
    final String SAVING_ACCOUNT = "SAVING";

    public Account getAccount(String accountType){
        if(CURRENT_ACCOUNT.equals(accountType)) {
            return new CurrentAccount();
        }
        else if(SAVING_ACCOUNT.equals(accountType)){
            return new SavingAccount();
        }
        return null;
    }
}

Abstract factory

这是一个比工厂模式高级的设计模式。使用抽象工厂模式,你只定义一个接口或者抽象类来增加有关的依赖对象,而不指定具体子类。所以,抽象工厂返回的是类的工厂。比如,我们有一些工厂类,把这些工厂放到一个工厂里,就是说有了一个工厂的工厂。
抽象工厂带来的好处:

  • 在组件族之间提供了松耦合
  • 提供了对象构造时的一致性

Spring中的Abstract factory

FactoryBean接口就是基于抽象工厂设计模式的。Spring提供了它的很多实现,比如ProxyFactoryBean、JndiFactoryBean、LocalSessionFactoryBean和LocalContainerEntityManagerFactoryBean等。它有助于构造依赖关系比较复杂的bean,也有助于构造可变化的或者依赖配置的bean。
比如,LocalSessionFactoryBean用来获取与hibernate configuration相关的bean的引用。它是数据源相关的配置,在你从SessionFactory获取对象前它就应该应用了。你可以把getObject()返回的结果注入其他属性。

简单的例子

Abstract Factory

public interface Bank {
    void bankName();
}

public class ICICIBank implements Bank {
    @Override
    public void bankName() {
        System.out.println("ICICI Bank Ltd.");
    }
}

public class YesBank implements Bank{
    @Override
    public void bankName() {
        System.out.println("Yes Bank Pvt. Ltd.");
    }
}



下面是工厂类

public abstract class AbstractFactory {
    abstract Bank getBank(String bankName);
    abstract Account getAccount(String accountType);
}

public class BankFactory extends AbstractFactory {
    final String ICICI_BANK = "ICICI";
    final String YES_BANK = "YES";

    @Override
    Bank getBank(String bankName) {
        if(ICICI_BANK.equalsIgnoreCase(bankName)) {
            return new ICICIBank();
        }
        else if(YES_BANK.equalsIgnoreCase(bankName)) {
            return new YesBank();
        }
        return null;
    }
    
    @Override
    Account getAccount(String accountType) {
        return null;
    }
}

public class FactoryProducer {
    final static String BANK = "BANK";
    final static String ACCOUNT = "ACCOUNT";
    
    public static AbstractFactory getFactory(String factory) {
        if(BANK.equalsIgnoreCase(factory)) {
            return new BankFactory();
        }
        else if(ACCOUNT.equalsIgnoreCase(factory)) {
            return new AccountFactory();
        }
        return null;
    }
}

测试代码

public class FactoryPatterMain {
    public static void main(String[] args) {
        AccountFactory accountFactory = new AccountFactory();

        Account savingAccount = accountFactory.getAccount("SAVING");
        savingAccount.accountType();

        Account currentAccount = accountFactory.getAccount("CURRENT");
        currentAccount.accountType();
    }
}

Singleton

带来的好处:

  • 可以控制对关键类(一般是比较重的对象)的访问,比如数据库连接池
  • 节省堆内存
  • 在多线程环境里很高效
  • 更灵活。因为控制了实例化的过程,所以更方便修改
  • 低延迟

Spring 中的应用

Singleton scoped bean就使用了单例模式。此时,每个容器里一个bean的实例。

public class SingletonClass {
    private static final SingletonClass INSTANCE = new SingletonClass();
    private SingletonClass() {}
    public static SingletonClass getInstance() {
        return INSTANCE;
    }
}

Prototype

该模式使用对象的clone方法增加对象。如果直接增加对象比较费时,可以用原型模式。比如,通过费时的数据库操作,我们增加了一个对象。然后缓存该对象,在下一次请求时,返回它的clone,如果需要,可以更新数据库,这样减少了数据库操作。

带来的好处:

  • 减少了子类
  • 在运行时增加和删除对象

简单的例子

Prototype

先增加抽象的Account类,再增加具体的子类

public abstract class Account implements Cloneable{
    abstract public void accountType();
    
    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

public class CurrentAccount extends Account {
    @Override
    public void accountType() {
        System.out.println("CURRENT ACCOUNT");
    }
}

public class SavingAccount extends Account {
    @Override
    public void accountType() {
        System.out.println("SAVING ACCOUNT");
    }
}

再增加AccountCache类,使用HashMap保存帐号对象,请求的时候返回对象的克隆

public class AccountCache {
    public static Map<String, Account> accountCacheMap = new HashMap<>();
    static{
        Account currentAccount = new CurrentAccount();
        Account savingAccount = new SavingAccount();
        accountCacheMap.put("SAVING", savingAccount);
        accountCacheMap.put("CURRENT", currentAccount);
    }
}

下来是测试代码

public class PrototypePatternMain {
    public static void main(String[] args) {
        Account currentAccount = (Account)
                AccountCache.accountCacheMap.get("CURRENT").clone();
        currentAccount.accountType();
        
        Account savingAccount = (Account)
                AccountCache.accountCacheMap.get("SAVING") .clone();
        savingAccount.accountType();
    }
}

Builder

Builder设计模式一步步地构造复杂对象,最终返回完整的对象。

Spring中的Builder

Spring不少地方使用了Builder模式,比如:EmbeddedDatabaseBuilder、AuthenticationManagerBuilder、UriComponentsBuilder、BeanDefinitionBuilder等。

简单的例子


public class Account {
    private String accountName;
    private Long accountNumber;
    private String accountHolder;
    private double balance;
    private String type;
    private double interest;
    
    private Account(AccountBuilder accountBuilder) {
        super();
        this.accountName = accountBuilder.accountName;
        this.accountNumber = accountBuilder.accountNumber;
        this.accountHolder = accountBuilder.accountHolder;
        this.balance = accountBuilder.balance;
        this.type = accountBuilder.type;
        this.interest = accountBuilder.interest;
    }

    
    public static class AccountBuilder {
        private final String accountName;
        private final Long accountNumber;
        private final String accountHolder;
        private double balance;
        private String type;
        private double interest;
        public AccountBuilder(String accountName,
                              String accountHolder, Long accountNumber) {
            this.accountName = accountName;
            this.accountHolder = accountHolder;
            this.accountNumber = accountNumber;
        }
        public AccountBuilder balance(double balance) {
            this.balance = balance;
            return this;
        }
        public AccountBuilder type(String type) {
            this.type = type;
            return this;
        }
        public AccountBuilder interest(double interest) {
            this.interest = interest;
            return this;
        }
        public Account build() {
            Account user = new Account(this);
            return user;
        }
    }
    public String toString() {
        return "Account [accountName=" + accountName + ", accountNumber=" + accountNumber +
                ", accountHolder=" + accountHolder + ", balance=" + balance + ", type="
                + type + ", interest=" + interest + "]";
    }
}

测试代码

public class AccountBuilderTest {
    public static void main(String[] args) {
        Account account = new Account.AccountBuilder("SavingAccount", "Dinesh Rajput", 1111l)
                .balance(38458.32)
                .interest(4.5)
                .type("SAVING")
                .build();
        System.out.println(account);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值