设计模式几乎是所有程序员都在研究东西,它代表着最佳实践,用设计模式可以让自己的软件变得更加优秀,在开发中让代码变得更加优雅。如果在面试的时候候选人可以将一些设计模式的内容,并且有些实战经验,也会在面试中脱颖而出。那今天就讲讲两个常用的设计模式,工厂模式和策略模式。
设计模式原则
面向对象的设计模式有七大基本原则:
开闭原则(Open Closed Principle,OCP)
单一职责原则(Single Responsibility Principle, SRP)
里氏代换原则(Liskov Substitution Principle,LSP)
依赖倒转原则(Dependency Inversion Principle,DIP)
接口隔离原则(Interface Segregation Principle,ISP)
合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
最少知识原则(Least Knowledge Principle,LKP)或者迪米特法则(Law of Demeter,LOD)
简单理解就是:开闭原则是总纲,它指导我们要对扩展开放,对修改关闭;单一职责原则指导我们实现类要职责单一;里氏替换原则指导我们不要破坏继承体系;依赖倒置原则指导我们要面向接口编程;接口隔离原则指导我们在设计接口的时候要精简单一;迪米特法则指导我们要降低耦合。
所有设计模式都是遵从一以上原则的,简单理解,使用设计模式的目的是为了可重用代码,提高代码的可扩展性和可维护性。
工厂模式
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
工厂模式类图
示例代码:
//抽象的产品
public abstract class Product {
public abstract void method();
}
//定义一个具体的产品 (可以定义多个具体的产品)
class ProductA extends Product {
@Override
public void method() {} //具体的执行逻辑
}
//抽象的工厂
abstract class Factory<T> {
abstract Product createProduct(Class<T> c);
}
//具体的工厂根据不用的产品类创建不同的类
class FactoryA extends Factory{
@Override
Product createProduct(Class c) {
Product product = (Product) Class.forName(c.getName()).newInstance();
return product;
}
}
策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
策略模式类图
示例代码:
//定义一个策略接口
public interface Strategy {
void strategyImplementation();
}
//具体的策略实现(可以定义多个具体的策略实现)
public class StrategyA implements Strategy{
@Override
public void strategyImplementation() {
System.out.println("正在执行策略A");
}
}
//封装策略,屏蔽高层模块对策略、算法的直接访问,屏蔽可能存在的策略变化
public class Context {
private Strategy strategy = null;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void doStrategy() {
strategy.strategyImplementation();
}
}
举个实际的例子来更好理解一下,比如我们每天上班出行根据当天路况可能有不同的出行策略,比如,骑车,地铁,开车。
//抽象策略
public abstract class TravelStrategy {
public abstract void travel();
public void insertRewardAndSettlement(long userId, int reward) {} ; //更新用户信息以及结算
}
//骑车
public class BicycleStrategy extends TravelStrategy {
@Override
public void travel() {}
}
//地铁
public class SubwayStrategy extends TravelStrategy {
@Override
public void travel() {}
}
//开车
public class DriveStrategy extends TravelStrategy {
@Override
public void travel() {}
}
//抽象工厂
public abstract class StrategyFactory<T> {
abstract TravelStrategy createStrategy(Class<T> c);
}
//具体工厂创建具体的策略
public class FactorTravelStrategyFactory extends StrategyFactory {
@Override
TravelStrategy createStrategy(Class c) {//传入不同的出行方式就会实例化不同的类
TravelStrategy travel = null;
try {
product = (TravelStrategy) Class.forName(c.getName()).newInstance();
} catch (Exception e) {}
return travel;
}
}
通过工厂模式生产出具体的策略之后,根据我们之前的介绍,很容易就可以想到使用策略模式来执行我们的策略。具体代码如下:
public class TravelContext {
private TravelStrategy strategy;
public TravelContext(TravelStrategy strategy) {
this.strategy = strategy;
}
public void doStrategy() {
strategy.travel();
}
}
public class TravelImpl {
//主流程
public void decideWayOfTravel() {
FactorTravelStrategyFactory strategyFactory = new FactorTravelStrategyFactory(); //创建工厂
int trafficCondition = getTrafficCondition(); //获取交通天气情况信息
if (trafficCondition == TrafficCondition.TRAFFIC_JAM) { //交通拥堵
SubwayStrategy subwayStrategy = (SubwayStrategy) strategyFactory.createStrategy(SubwayStrategy.class);
TravelContext travelContext = new TravelContext(subwayStrategy);
travelContext.doStrategy(); //执行策略
}else if(trafficCondition == TrafficCondition.TRAFFIC_CLEAR){ //道路通畅
DriveStrategy driveStrategy = (DriveStrategy) strategyFactory.createStrategy(DriveStrategy.class);
TravelContext travelContext = new TravelContext(driveStrategy);
travelContext.doStrategy(); //执行策略
} else if ...
}
}
工厂方法模式帮助我们直接产生一个具体的出行策略对象,策略模式帮助我们保证这些出行策略对象可以自由地切换而不需要改动其他逻辑,从而达到解耦的目的。通过这两个模式的组合,当我们系统需要增加一种出行策略时,只需要实现TravelStrategy接口即可,无需考虑其他的改动。当我们需要改变策略时,只要修改策略的类名即可。不仅增强了系统的可扩展性,避免了大量的条件判断,而且从真正意义上达到了高内聚、低耦合的目的。
欢迎大家关注,vx公众号同名