说明
本文只对策略枚举可以使用的场景进行说明,不做其他介绍。提供额外的实现思路。
工厂模式
普通的工厂模式,都有一个基本的抽象类或接口,然后具体的实现类。并且由一个工厂类来进行返回实现类。
参考:工厂模式
改造
这里对参考的代码进行改造:
- Shape.java、Rectangle.java、Square.java、Circle.java,这四个类不变。
- 在ShapeFactory.java类中,存在一个类型:"shapeType"。这个就能够使用枚举进行替换。所以我们就新建一个枚举ShapeTypeEnum.java。如下:
- 删除将ShapeFactory.java中的getShape方法,使用ShapeTypeEnum.java的valueOf和getShape方法代替。就可以实现工厂模式到策略工厂的转换。
public enum ShapeTypeEnum {
CIRCLE(new Circle()),
RECTANGLE(new Rectangle()),
SQUARE(new Square()),
;
private Shape shape;
ShapeTypeEnum(Shape shape) {
this.shape = shape;
}
public Shape getShape() {
return shape;
}
}
- 在使用的地方,代码修改为:
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
System.out.println("***************************************************");
// 可能存在空指针异常,可以进一步优化 ShapeTypeEnum 类
ShapeTypeEnum.valueOf("CIRCLE").getShape().draw();
ShapeTypeEnum.valueOf("RECTANGLE").getShape().draw();
ShapeTypeEnum.valueOf("SQUARE").getShape().draw();
}
}
最终结果与原来的一致。
优点
- 如果shapeType增加了,我们可以通过修改枚举的时候,马上就能够发现,需要添加一个对应的实现。
- 天然的单例实现。如果想要实现多利,也能够通过改造ShapeTypeEnum实现。
缺点
前期代码量会有点大,但是基本属于框架性代码
优化
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public enum ShapeTypeEnum {
DEFAULT("", new Default()) {
@Override
public Shape getShapeImpl() {
return new Default();
}
},
CIRCLE("CIRCLE", new Circle()) {
@Override
public Shape getShapeImpl() {
return new Circle();
}
},
RECTANGLE("RECTANGLE", new Rectangle()) {
@Override
public Shape getShapeImpl() {
return new Rectangle();
}
},
SQUARE("SQUARE", new Square()) {
@Override
public Shape getShapeImpl() {
return new Square();
}
},
;
/**
* 功能描述: 获取实现 <br/>
*
* @return "com.csdn.enums4.Shape"
*/
public abstract Shape getShapeImpl();
/**
* 功能描述: 单例 <br/>
*
* @param type 类型
* @return "com.csdn.enums4.Shape"
*/
public static Shape getSingletonShape(String type) {
return indexOf(type).getShape();
}
/**
* 功能描述: 非单例 <br/>
*
* @param type 类型
* @return "com.csdn.enums4.Shape"
*/
public static Shape getNonSingletonShape(String type) {
return indexOf(type).getShapeImpl();
}
private final static Map<String, ShapeTypeEnum> map = Stream.of(values()).collect(Collectors.toMap(ShapeTypeEnum::getType, e -> e));
public static ShapeTypeEnum indexOf(String type) {
// 避免出现空指针
return Optional.ofNullable(map.get(type)).orElse(DEFAULT);
}
private final String type;
private final Shape shape;
ShapeTypeEnum(String type, Shape shape) {
this.type = type;
this.shape = shape;
}
public String getType() {
return type;
}
public Shape getShape() {
return shape;
}
}
每个draw实现的输出,都加上输出当前对象this
@Override
public void draw() {
System.out.println("Inside Default::draw() method." + this);
}
使用
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
System.out.println("*************************单例****************************");
ShapeTypeEnum.getSingletonShape("CIRCLE").draw();
ShapeTypeEnum.getSingletonShape("CIRCLE").draw();
ShapeTypeEnum.getSingletonShape("RECTANGLE").draw();
ShapeTypeEnum.getSingletonShape("RECTANGLE").draw();
ShapeTypeEnum.getSingletonShape("SQUARE").draw();
ShapeTypeEnum.getSingletonShape("SQUARE").draw();
System.out.println("**********************非单例*****************************");
ShapeTypeEnum.getNonSingletonShape("CIRCLE").draw();
ShapeTypeEnum.getNonSingletonShape("CIRCLE").draw();
ShapeTypeEnum.getNonSingletonShape("RECTANGLE").draw();
ShapeTypeEnum.getNonSingletonShape("RECTANGLE").draw();
ShapeTypeEnum.getNonSingletonShape("SQUARE").draw();
ShapeTypeEnum.getNonSingletonShape("SQUARE").draw();
}
}
结果
Inside Circle::draw() method.com.csdn.enums4.Circle@677327b6
Inside Rectangle::draw() method.com.csdn.enums4.Rectangle@14ae5a5
Inside Square::draw() method.com.csdn.enums4.Square@7f31245a
*************************单例****************************
Inside Circle::draw() method.com.csdn.enums4.Circle@5b480cf9
Inside Circle::draw() method.com.csdn.enums4.Circle@5b480cf9
Inside Rectangle::draw() method.com.csdn.enums4.Rectangle@6f496d9f
Inside Rectangle::draw() method.com.csdn.enums4.Rectangle@6f496d9f
Inside Square::draw() method.com.csdn.enums4.Square@723279cf
Inside Square::draw() method.com.csdn.enums4.Square@723279cf
**********************非单例*****************************
Inside Circle::draw() method.com.csdn.enums4.Circle@10f87f48
Inside Circle::draw() method.com.csdn.enums4.Circle@b4c966a
Inside Rectangle::draw() method.com.csdn.enums4.Rectangle@2f4d3709
Inside Rectangle::draw() method.com.csdn.enums4.Rectangle@4e50df2e
Inside Square::draw() method.com.csdn.enums4.Square@1d81eb93
Inside Square::draw() method.com.csdn.enums4.Square@7291c18f