设计模式之简单工厂、策略模式

引言

原文链接:带你读懂几种常见的设计模式 第一弹 希望点进去的小伙伴关注一下我的公众号哟,文末有二维码,谢谢!

写设计模式的目的主要是为了后面写spring系列文章做铺垫。大家都知道,spring运用了大量的设计模式,因此复习一遍设计模式对学spring是有好处的。当然,设计模式同样重要!

1、设计模式的六大原则

单一职责原则

  • 每个类的职责尽量单一。这个在实际项目中很难做到。

开闭原则

  • 对扩展开放,对修改关闭。这个原则还是很重要的。

里氏代换原则

  • 只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。这个原则挺不好理解的。

依赖倒转原则

  • 针对接口编程,依赖于抽象而不依赖于具体。

接口隔离原则

  • 使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

迪米特(最少知道)法则

  • 一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

合成复用原则

  • 尽量使用合成/聚合的方式,而不是使用继承。这个原则不属于六大原则,但是十分重要

良好的代码总是有如下特性:

  • 可维护

  • 可复用

  • 可扩展

  • 灵活性高

2、设计模式分类

创建型模式:提供一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 直接实例化对象。

工厂模式

抽象工厂模式

单例模式

建造者模式

原型模式

结构型模式

适配器模式

桥接模式

过滤器模式

组合模式

装饰器模式

外观模式

享元模式

代理模式

行为型模式:关注对象之间的通信。

责任链模式

命令模式

解释器模式

迭代器模式

中介者模式

备忘录模式

观察者模式

状态模式

空对象模式

策略模式

模板模式

访问者模式

J2EE模式:关注表示层。

MVC 模式

业务代表模式

组合实体模式

数据访问对象模式

前端控制器模式

拦截过滤器模式

服务定位器模式

传输对象模式

3、简单工厂模式

简单工厂模式确实挺简单,直接上例子。

首先定义接口。

public interface Animal {
    void sayHello();
}

然后定义Animal的实现,Cat、Dog、Pig。

class Cat implements Animal{
    @Override
    public void sayHello() {
        System.out.println("Cat say Hello");
    }
}

class Dog implements Animal{
    @Override
    public void sayHello() {
        System.out.println("Dog say Hello");
    }
}

class Pig implements Animal{
    @Override
    public void sayHello() {
        System.out.println("Pig say Hello");
    }
}

构建一个动物工厂,通过输入不同动物的名字,来获取不同的动物对象。

public class AnimalFactory {

    public static Animal getAnimal(String name){
        Animal animal = null;
        switch (name){
            case "cat":
                animal = new Cat();
                break;
            case "dog":
                animal = new Dog();
                break;
            case "pig":
                animal = new Pig();
                break;
            default:
                ;
        }
        return animal;
    }
}

最后写一个main方法运行。

public class SimpleFactoryTest {
    public static void main(String[] args) {
        Animal animal = AnimalFactory.getAnimal("dog");
        animal.sayHello();

    }
}

简单工厂模式不符合开闭原则,为什么呢?如果我想让动物工厂能生产老虎、狮子、大象,那除了增加老虎、狮子、大象类之外,还需要修改AnimalFactory类。

4、策略模式

先不说策略模式的定义,直接来看一个场景吧。

在逛商场的最后支付的时候,商场可能当天在搞活动,比如打折活动、满减活动,也可能没有活动。

根据不同的活动,会有不同的收费方式。比如当天打8折,那么收费方式就是购买商品总价的基础上乘以0.8;如果没有活动,则收费方式是全额。

在这里,收费方式可以当作一种策略。根据老板的要求,收费员可以随意切换收费策略。

说了这么多,再说说策略模式的定义吧:策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换

根据上述所说的场景,下面就来实现一个策略模式。

首先,定义一个公用的策略接口。

public interface PayStrategy {
    /**
     * @param price 客户购买商品的总价
     * @return 客户最终需要支付的钱
     */
    double getResult(double price);
}

然后,定义三类策略,分别是支付全额、打折支付、满减支付。

/**
 * 全额支付
 */
public class PayAll implements PayStrategy {
    @Override
    public double getResult(double price) {
        return price;
    }
}

/**
 * 打折支付
 */
public class PayByRebate implements PayStrategy {
    private double rebate;

    /**
     * 具体打几折
     */
    public PayByRebate(double rebate) {
        this.rebate = rebate;
    }

    @Override
    public double getResult(double price) {
        return price*rebate;
    }
}

/**
 * 满减支付
 */
public class PayByReturn implements PayStrategy {
    private double condition;
    private double money;

    /**
     * 具体满多少减多少
     */
    public PayByReturn(double condition, double money) {
        this.condition = condition;
        this.money = money;
    }

    @Override
    public double getResult(double price) {
        if (price >= condition){
            return price-money;
        }else{
            return price;
        }
    }
}

到此,三种策略类都定义好了,其实程序已经可以工作。但是我们可以想象一个,收费员的电脑上有一个收费页面,该页面上有一个下拉框,该下拉框的选项有正常收费、打八折、满300减100,正好对应上面的三种策略类,但是当收费员选择好收费策略,然后后台去计算需要支付多少钱的时候,难道要去new一个具体的策略类吗?

因为,我们可以将策略模式与简单工厂模式结合起来,再构建一个上下文类。

public class PayContext {

    private PayStrategy payStrategy;

    public PayContext(String type){
        switch (type){
            case "正常收费":
                payStrategy = new PayAll();
                break;
            case "打八折":
                payStrategy = new PayByRebate(0.8);
                break;
            case "满300减100":
                payStrategy = new PayByReturn(300,100);
                break;
            default:
                ;
        }
    }
    public double getResultByStrategy(double price){
        return payStrategy.getResult(price);
    }
}

细心的读者会发现,上下文类与简单工厂模式中的工厂类还是有点不同的。

工厂类会返回一个父类对象,然后客户端再调用父类对象的方法,这样客户端能感知到父类。

而简单工厂模式+策略模式相结合,父类对象隐藏在上下文对象里,客户端    通过调用上下文对象的getResultByStrategy()方法,返回的是客户端想要的最终结果,而感知不到父类的存在,这样更加降低了客户端与上下文类之间的耦合度。

最后,我们下一个main方法测试一下。

public class StrategyTest {
    public static void main(String[] args) {
        PayContext pc = new PayContext("满300减100");
        double d = pc.getResultByStrategy(500);
        System.out.println(d);
    }
}

今天的文章就到这里了。设计模式系列文章我更关注实际案例,所以代码会比较多,考虑到文章篇幅,本文只介绍了两种设计模式,下一篇文章会介绍更多的设计模式。

我的二维码

觉得写得不错的小伙伴,扫码关注一下我的公众号吧,谢谢呀!

猜你喜欢

转载自blog.csdn.net/xl_1803/article/details/112006829