代码中的设计模式2----策略模式、工厂模式

为什么要在代码中使用设计模式,因为代码最重要的是要让别人看懂。在一些优秀的开源项目中,大量的使用了设计模式,代码的可读性非常高。在实际的项目开发中,针对一些特定的场景使用设计模式,能让代码可读性更高,扩展性更强。

1 策略模式

策略,Strategy。在解决一个问题的时候,可能会有很多种解法,每种解法对应一个算法,针对不同的场景随意切换,提高代码的灵活性。优势在于在需要修改时,只需要针对某个策略修改,不需要动整体框架。

例如北京公交车,10km以内1元钱,超过10km之外的,没超出5km就会多加1元钱;北京地铁,6km内3元,6-12km(含)内4元,12-22km(含)内5元,22-32km(含)内6元。

两种策略:公交和地铁出行,根据里程数,计算出对应的价格。

1.1 基础策略模式

public class PriceCalculator {


    public enum TYPE{
        BUS,SUBWAY
    }

    public static void main(String[] args){

        PriceCalculator priceCalculator = new PriceCalculator();
        int busPrice = priceCalculator.calculatePrice(20,TYPE.BUS);
        int subwayPrice = priceCalculator.calculatePrice(10,TYPE.SUBWAY);

        System.out.println("20km公交车的价格:"+busPrice+",20km地铁的价格:"+subwayPrice);
    }
    /**
     * 策略1 乘坐公交车
     * @param km
     * @return
     */
    public int busPrice(int km){
        //基础价格10元,10km以内
        int basePrice = 1;
        //超出的公里数
        int offsetDistance = km - 10;
        //没有超出10km
        if(offsetDistance < 0){
            return  basePrice;
        }
        //计算超出5km的
        int radio = offsetDistance / 5;

        return basePrice + radio * 1;
    }

    /**
     * 策略2 乘坐地铁
     * @param km
     * @return
     */
    public int subwayPrice(int km){

        if(km <= 6){

            return 3;
        }else if(km > 6 && km <= 12){
            return 4;
        }else if(km > 12 && km <= 22){

            return 5;
        }else if(km > 22 && km <= 32){
            return  6;
        }

        return 7;
    }

    /**
     * 针对不同的策略,计算相应的价格
     * @param km
     * @param type
     * @return
     */
    public int calculatePrice(int km,TYPE type){

        if(type == TYPE.BUS){

            return busPrice(km);
        }else if(type == TYPE.SUBWAY){
            return subwayPrice(km);
        }

        return -1;
    }
}

这种框架存在的问题包括:
(1)PriceCalculator 违背了单一职责原则,不仅计算了公交的价格,还计算了地铁的价格;
(2)calculatePrice方法,使用了if-else来判断使用哪个策略,违背了开闭原则,如果有1000种方式,那么需要写1000个if-else。

所以,策略模式,就是用来代替if-else,可动态地选择对应的策略。

1.2 动态策略模式

第一步:新建一个接口,其中设置各个策略类计算价格的方法。

public interface IPriceStrategy {
	//计算价格
    int price(int km);
}

第二步:不同策略实现类实现该接口

public class BusPriceStrategy implements IPriceStrategy{
    @Override
    public int price(int km) {

        //基础价格1元,10km以内
        int basePrice = 1;
        //超出的公里数
        int offsetDistance = km - 10;
        //没有超出10km
        if(offsetDistance < 0){
            return  basePrice;
        }
        //计算超出5km的
        int radio = offsetDistance / 5;

        return basePrice + radio * 1;
    }
}

public class SubwayStrategy implements IPriceStrategy{
    @Override
    public int price(int km) {
        if(km <= 6){

            return 3;
        }else if(km > 6 && km <= 12){
            return 4;
        }else if(km > 12 && km <= 22){

            return 5;
        }else if(km > 22 && km <= 32){
            return  6;
        }

        return 7;
    }
}

每个策略实现类的价格算法,都是之前PriceCalculator 类中拷贝过来的。

第三步:策略上下文,统一调度策略算法。

public class PriceStrategy {

    private IPriceStrategy mStrategy;

    public PriceStrategy(){}

    /**
     * 动态调度算法
     * @param strategy
     */
    public void setStrategy(IPriceStrategy strategy){

        this.mStrategy = strategy;
    }

    /**
     * 根据具体实现类,调用价格计算的方法
     * @param km
     * @return
     */
    public int calculatePrice(int km){
        return mStrategy.price(km);
    }
}

通过setStrategy方法来切换对应的策略,避免使用if-else是的代码变得臃肿,难以维护。如果价格的计算方式改变,只需要改变BusPriceStrategy或者SubwayStrategy两个类的计算算法,整体调用的框架,在这里是不需要修改的,具备扩展性。

PriceStrategy priceStrategy = new PriceStrategy();
priceStrategy.setStrategy(new BusPriceStrategy());
int busPrice = priceStrategy.calculatePrice(20);
priceStrategy.setStrategy(new SubwayStrategy());
int subwayPrice = priceStrategy.calculatePrice(20);

System.out.println("20km公交车的价格:"+busPrice+",20km地铁的价格:"+subwayPrice);

2 工厂模式

工厂模式可用户构建复杂的对象,如果通过new就能创建的对象没有必要使用工厂模式。

例如,A工厂生产A类产品,B工厂生产B类产品…

2.1 简单工厂模式

public interface IProduct {
    //产品
    void create();
}

A产品

public class AProduct implements IProduct{
    @Override
    public void create() {
        System.out.println("我是A类工厂的A产品");
    }
}

B产品

public class BProduct implements IProduct {
    @Override
    public void create() {
        System.out.println("我是B类工厂的B产品");
    }
}

简单工厂方法,通过if-else判断产品类型来生成对应的产品,缺点在策略模式中讲过,在此不过多赘述。

public class ProductFactory {

    enum Product{
        A,B
    }

    private IProduct mProduct;
    //根据Product类型判断
    public void createProduct(Product product){

        if(product == Product.A){

            mProduct= new AProduct ();
        }else if(product == Product.B){

            mProduct= new BProduct ();
        }
    }

    public void create(){
        mProduct.create();
    }
}

简单工厂模式,仅适用于产品固定的场景(这种场景基本很少出现),否则将会违背开闭原则。每增加一个产品,需要添加一次if-else。

	@Test
    public void test(){


        ProductFactory factory = new ProductFactory();
        factory.createProduct(ProductFactory.Product.A);
        factory.create();
//        AFactory
    }

2.2 工厂方法模式

工厂方法模式解决了简单工厂模式的弊端,每个产品对应一个工厂。

/**
 * 工厂方法模式
 */
public interface IFactoryBuild {
    //创建工厂的方法
    IProduct build();
}

A工厂

public class AFactory implements IFactoryBuild {


    @Override
    public IProduct build() {
    	//生成A产品
        return new AProduct();
    }
}

B工厂

public class BFactory implements IFactoryBuild {

    @Override
    public IProduct build() {
        return new BProduct();
    }
}

根据需求,如果需要生产A产品,就创建A类工厂,生产B产品就创建B类工厂。

AFactory aFactory = new AFactory();
IProduct product = aFactory.build();
product.create();

弊端在于,如果存在很多工厂,那么需要创建很多工厂。

public class ProductFactory {


    public IFactoryBuild createFactory(Class<? extends IFactoryBuild> mFactory){

        try {
            return mFactory.newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

        return null;
    }
}

2.3 抽象工厂设计模式

抽象工厂设计模式与工厂方法一致,只不过抽象工厂模式适用于大规模批量生产的场景。

例如不同的手机,性能配置都不同。小米手机配置的是高通CPU,8核,红米手机配置的是联发科CPU,4核,那么使用抽象工厂设计模式,设计对应的手机。

产品:CPU、核心数、小米手机、红米手机

public interface CPU {

    void run();
    
	class GaotongCpu implements CPU{

        @Override
        public void run() {
            System.out.println("高通CPU");
        }
    }

    class lianfakeCpu implements CPU{

        @Override
        public void run() {
            System.out.println("联发科CPU");
        }
    }
}
public interface Core {

    void run();
    
    class core8 implements Core{

        @Override
        public void run() {
            System.out.println("8核");
        }
    }

    class core4 implements Core{

        @Override
        public void run() {
            System.out.println("4核");
        }
    }
}

工厂:小米工厂、红米工厂

public interface IMobileFactory {

    CPU getCpu();
    Core getCore();
    
}
public class XiaoMiFactory implements IMobileFactory {
    @Override
    public CPU getCpu() {
        //高通的CPU
        return new CPU.GaotongCpu();
    }

    @Override
    public Core getCore() {
        //8核
        return new Core.core8();
    }
}
public class RedMiFactory implements IMobileFactory{
    @Override
    public CPU getCpu() {
        return new CPU.lianfakeCpu();
    }

    @Override
    public Core getCore() {
        return new Core.core4();
    }
}
XiaoMiFactory factory = new XiaoMiFactory();
factory.getCpu().run();
factory.getCore().run();

输出结果:

高通CPU
8
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awesome_lay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值