一些常规问题在Scala中的不同解法
创建单例
Singleton (Java)
public class ClassicSingleton {
private static ClassicSingleton instance = null;
protected ClassicSingleton() {
// Exists only to defeat instantiation.
}
public static ClassicSingleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
}
Singleton(Scala)
object ScalaSingleton {
def printSomething() {
println("printSomething")
}
}
被简化掉的东西:
- 静态私有字段
- 外界不可访问的constructor
- 对字段的判空与初始化
声明类
构造函数
属性
Constructor
class ScalaConstructorExample(val x: Double, y: String) {
println(x + y)
}
Constructor
public class ScalaConstructorExample
{
private final double x;
public double x()
{
return this.x;
}
public ScalaConstructorExample(double x, String y)
{
Predef..MODULE$.println(new StringBuilder().append(x).append(y).toString());
}
}
被简化掉的东西:
- 声明字段
- 为只读属性创建getter
- 为可读写属性创建setter
给两个没有太多关联的继承体系内的两个类消除重复代码
假设已有如下两个继承体系:
abstract class Plant {
def photosynthesis = println("Oh, the sunlight!")
}
class Rose extends Plant {
def smell = println("Good!")
def makePeopleHappy = println("People like me")
}
class Ruderal extends Plant {
def grow = println("I take up all the space!")
}
abstract class Animal {
def move = println("I can move!")
}
class Dog extends Animal {
def bark = println("Woof!")
def makePeopleHappy = println("People like me")
}
class Snake extends Animal {
def bite = println("I am poisonous!")
}
常见解决方案1
对继承体系下手,抽取公共父类,将共同行为置于其中。
常见解决方案2
创建一个接口,将共同行为声明于其中。同时提供一个静态方法,来实现共同行为。每一个实现该接口的类,都调用该静态方法。
trait
trait PeoplePleaser {
def makePeopleHappy = println("People like me")
}
class Rose extends Plant with PeoplePleaser {
def smell = println("Good!")
}
class Dog extends Animal with PeoplePleaser {
def bark = println("Woof!")
}
被简化掉的东西:
- 触碰已有继承体系
- 将接口和实现分开声明
- 在每个实现类中调用静态方法
Lazy evaluation
Lazy (Java)
private String str = null;
public String getStr() {
if (str == null) {
str = getStrFromWebService();
}
return str;
}
Lazy(C#)
private Lazy<String> str = new Lazy<string> (() => GetStrFromWebService ());
public String Str
{
get
{
return str.Value;
}
}
Lazy(Scala)
lazy val str = getStrFromWebService()
被简化掉的东西:
- 分开声明字段与属性
- 对字段判空
- 自己写代码判断web service是否已经被请求过
类型判断,类型转换,取属性,属性值判断
假设已有如下类:
abstract class Animal
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal
Java
Animal animal = createAnimal();
String result = "other animal";
if (animal instanceof Dog) {
result = "this is a dog";
} else if (animal instanceof Cat) {
Cat cat = (Cat) animal;
if (cat.name() == "kitty") {
result = "this is a cat named kitty";
}
}
return result;
Scala
val animal = createAnimal
animal match {
case Dog(anyName) => "this is a dog"
case Cat("kitty") => "this is a cat named kitty"
case _ => "other animal"
}
被简化掉的东西:
- 类型判断
- 类型转换
- 取属性
- 属性值判断
Adapter模式
Adapter
class Duck {
def makeDuckNoise() = "gua gua"
}
class Chicken {
def makeChickenNoise() = "ge ge"
}
def giveMeADuck(duck: Duck) = duck.makeDuckNoise()
giveMeADuck(new Duck)
class Ducken(chicken: Chicken) extends Duck {
override def makeDuckNoise() = chicken.makeChickenNoise()
}
giveMeADuck(new Ducken(new Chicken))
Implicit Function
implicit def chickenToDuck(chicken: Chicken) = new Ducken(chicken)
giveMeADuck(new Chicken)
被简化掉的东西:
- 每次适配都创建适配器实例的代码
- 嵌套的噪音
先判空,再运算
常规做法
def calculateTotal: Option[Int] = {
val price: Option[Int] = getPrice
val amount: Option[Int] = getAmount
if (price.isEmpty || amount.isEmpty) {
None
} else {
Some(price.get * amount.get)
}
}
简化的做法
def calculateTotalWithFor: Option[Int] = {
for (price <- getPrice; amount <- getAmount) yield price * amount
}
被简化掉的东西:
- 判断价格是否为空
- 判断数量是否为空