策略模式(Strategy)
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不通过的对象管理。
最典型的例子就是使用比较器(Comparator<T>
):
1 2 3 4 5 6
| @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import java.util.Arrays; import java.util.Comparator;
public class Cat { int weight;
public int GetWeight() { return weight; }
public Cat(int weight) { this.weight = weight; }
@Override public String toString() { return "Cat{" + "weight=" + weight + '}'; }
public static void main(String[] args) { Cat[] cats = {new Cat(12), new Cat(21), new Cat(4), new Cat(8)};
Arrays.sort(cats, Comparator.comparingInt(Cat::GetWeight));
System.out.println(Arrays.toString(cats)); } }
|
注:
- 开闭原则(OCP,Open-Closed Principle),对修改关闭,对扩展开放。
- 自定义静态泛型函数时,将类型参数列表写在
static
和返回值类型之间,例如:1
| static <T> void sort(T[] array, Comparator c);
|
抽象工厂(Abstract Factory)
一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
例如,农场可以生产动物、蔬菜。农场A生产牛,白菜,农场B生产羊,花椰菜。编码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public abstract class Farm { public abstract Animal createAnimal(); public abstract Vegetable createVegetable(); }
public interface Animal { }
public interface Vegetable { }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class FarmA extends Farm { @Override public Animal createAnimal() { return new Cow(); }
@Override public Vegetable createVegetable() { return new Cabbage(); } }
public class Cow implements Animal { }
public class Cabbage implements Vegetable { }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class FarmB extends Farm { @Override public Animal createAnimal() { return new Sheep(); }
@Override public Vegetable createVegetable() { return new Cauliflower(); } }
public class Sheep implements Animal { }
public class Cauliflower implements Vegetable { }
|
1 2 3 4 5 6 7 8
| public class Main { public static void main(String[] args) { Farm farm = new FarmA(); System.out.println(farm.createAnimal().getClass().getSimpleName()); System.out.println(farm.createVegetable().getClass().getSimpleName()); } }
|
输出:
使用 Rust 语言编写如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| use std::fmt::Debug;
trait Animal {} trait Vegetable {}
trait Farm { type A: Animal; type V: Vegetable; const NAME: &'static str;
fn create_animal() -> Self::A; fn create_vegetable() -> Self::V; }
#[derive(Debug)] struct Cow; impl Animal for Cow {} #[derive(Debug)] struct Cabbage; impl Vegetable for Cabbage {} struct FarmA; impl Farm for FarmA { type A = Cow; type V = Cabbage; const NAME: &'static str = "A";
fn create_animal() -> Self::A { Cow }
fn create_vegetable() -> Self::V { Cabbage } }
#[derive(Debug)] struct Sheep; impl Animal for Sheep {} #[derive(Debug)] struct Cauliflower; impl Vegetable for Cauliflower {} struct FarmB; impl Farm for FarmB { type A = Sheep; type V = Cauliflower; const NAME: &'static str = "B";
fn create_animal() -> Self::A { Sheep }
fn create_vegetable() -> Self::V { Cauliflower } }
fn run_a_farm<F>() where F: Farm, F::A: Debug, F::V: Debug, { println!("Farm {}:", F::NAME); println!("\tAnimal: {:?}", F::create_animal()); println!("\tVegetable: {:?}", F::create_vegetable()); }
fn main() { run_a_farm::<FarmA>(); run_a_farm::<FarmB>(); }
|
输出结果为:
1 2 3 4 5 6
| Farm A: Animal: Cow Vegetable: Cabbage Farm B: Animal: Sheep Vegetable: Cauliflower
|
典型应用场景
- 界面换肤,一款皮肤下,不同的控件的样式;
注:
- 增加新的产品族,只需要新增工厂实现,满足开闭原则;
- 产品族需要新增产品的时候,需要修改所有工厂,不满足开闭原则。
- 当系统只存在一类产品时,抽象工厂退化到工厂方法模式。
外观/门面(Facade)
通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。
它是迪米特法则的典型应用。降低了子系统与客户端之间的耦合度。
迪米特法则(LOD,Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。