设计模式——六种设计原则
1. 开闭原则:对扩展开放,对修改闭合
- 对扩展开放:有新的需求或变化时,通过现有代码进行扩展,来适应新的情况
- 对修改闭合:设计一旦完成,就可以独立完成工作,不对已有的代码进行任何修改
e.g. 动物园里有猫和狗,要求写出相应的叫声
public class AnimalCall{
public void call(Animal animal){
animal.call();
}
interface Animal{
void call();
}
class Cat implements Animal {
@Override
public void call() {
System.out.println("喵喵喵");
}
}
class Dog implements Animal {
@Override
public void call() {
System.out.println("汪汪汪");
}
}
}
各个动物有自己的叫声,Animal.call()只负责发声。当新增一只鸭子的叫声时,只需要增加鸭子的类,实现Animal接口,调用call()方法就可以发声了。整个过程中都只在扩展而没改变原来的类,符合开闭原则
2. 里氏替换原则:任何基类出现的地方,子类一定可以出现。也就是说子类可以扩展父类的功能,但不能改变父类原有的功能
e.g. 猫属于动物,动物会跑,那么猫也会跑,要求看猫多长时间(小时)能跑多远。
class Animal {
private double speed;
void setSpeed(double speed) {
this.speed = speed;
}
double getDistance(Integer time) {
return speed * time;
}
}
class Cat extends Animal {
}
public class RunTest {
public static void main(String[] args) {
Animal cat = new Cat();
cat.setSpeed(8);
System.out.println("如果跑两个小时:");
System.out.println("猫跑" + cat.getDistance(2) + "km");
}
}
================================================================
输出结果:
如果跑两个小时:
猫跑16.0km
3. 依赖倒转原则:高层模块不依赖低层模块,两者都依赖于其抽象;抽象不依赖于细节,细节应该依赖于抽象
依赖倒转原则是对开闭原则的具体实现
在设计模式中的体现:
- 简单工厂设计模式:在接口方法中注入
- 策略设计模式:在构造函数中注入
e.g. 有人,有猫,人可以撸猫,那如果有其他动物呢,人要如何摸呢
interface Animal {
void beTouch();
}
class Cat implements Animal {
@Override
public void beTouch() {
System.out.println("猫猫被摸了");
}
}
class Dog implements Animal {
@Override
public void beTouch() {
System.out.println("狗狗被摸了");
}
}
interface IPeople {
void touch(Animal animal);
}
class People implements IPeople {
@Override
public void touch(Animal animal) {
animal.beTouch();
}
}
class TouchTest {
public static void main(String[] args) {
IPeople people = new People();
people.touch(new Cat());
people.touch(new Dog());
}
}
=========================================================
输出结果:
猫猫被摸了
狗狗被摸了
4. 接口隔离原则:不依赖于不需要的方法上;一个类对另一个类的依赖应该建立在最小的接口上面
实现方法
- 接口尽量要小,但不要违反单一职责原则
- 接口要高内聚
- 定制服务(只提供访问者需要的方法)
- 接口设计有限度(了解业务逻辑)
e.g. 动物园有熊猫,可以观赏,喂养,打扫卫生等,比如游客只有观赏权限,饲养员拥有全部权限,该这么设计呢?
interface ILook {
void look();
}
interface IOperate {
void clean();
void feed();
}
class Visitor implements ILook {
@Override
public void look() {
System.out.println("游客观看了熊猫");
}
}
class feeder implements ILook, IOperate {
@Override
public void look() {
System.out.println("饲养员观看了熊猫");
}
@Override
public void clean() {
System.out.println("饲养员打扫了熊猫");
}
@Override
public void feed() {
System.out.println("饲养员喂养了熊猫");
}
}
5. 迪米特法则:又叫最少知识原则,也就是说,一个对象尽可能的少了解, ‘不和陌生人说话’
如果两个类不必直接通信,那么这两个类就不应当发生直接的相互作用,如果一个类需要调用另一个类的某个方法,可以通过“朋友”转发这个调用。
确定“朋友”的条件
- 当前对象本身(this)
- 以参数形式传入到当前对象方法中的对象
- 当前对象的实例变量如果是一个聚集,这聚集中的元素也都是朋友
- 当前对象所创建的对象
在设计模式中的应用
- 门面模式
- 中介模式
e.g. 一个人用洗衣机洗衣服,洗衣机洗衣服要三个方法:1. 放衣服,2. 放洗衣液,3. 洗衣
interface IWasher {
void wash();
}
class Washer implements IWasher {
private void addClothes() {
System.out.println("放衣服");
}
private void addLaundry() {
System.out.println("放洗衣液");
}
private void washClothes() {
System.out.println("洗衣服");
}
@Override
public void wash() {
this.addClothes();
this.addLaundry();
this.washClothes();
}
}
interface IPeople {
void washClothes();
}
class People implements IPeople {
private Washer washer;
public People(Washer washer) {
this.washer = washer;
}
@Override
public void washClothes() {
washer.wash();
}
}
class Client {
public static void main(String[] args) {
Washer washer = new Washer();
IPeople people = new People(washer);
people.washClothes();
}
}
=========================================================
输出结果:
放衣服
放洗衣液
洗衣服
6. 合成复合原则:尽量使用组合,聚合等关联关系来实现,其次才考虑继承关系实现
e.g. 汽车按颜色可划分为白色,红色,蓝色等,按能源划分可为汽油,柴油等
如果采用继承复用的话,排列组合就有六个子类,造成子类过多的情况,当增加新的颜色或能源的话,会违背开闭原则,所以采用聚合复用的方法,将颜色抽象,能源抽象,当增加新的颜色或能源的话,只需要扩展,不需要修改原来的代码
abstract class Car {
abstract void run();
private Color color;
Color getColor() {
return color;
}
void setColor(Color color) {
this.color = color;
}
}
interface Color {
void colorKind();
}
class PetrolCar extends Car {
@Override
void run() {
System.out.println("汽油汽车");
}
}
class White implements Color {
@Override
public void colorKind() {
System.out.println("白色");
}
}
class Test {
public static void main(String[] args) {
PetrolCar petrolCar = new PetrolCar();
White color = new White();
petrolCar.setColor(color);
petrolCar.getColor().colorKind();
petrolCar.run();
}
}
=================================================
输出结果:
白色
汽油汽车