这是我参与更文挑战的第16天,活动详情查看: 更文挑战
设计模式
设计原则我们已经讲了六种,单一职责原则、接口隔离原则、依赖倒转原则、里氏替换原则、开闭原则、迪米特法则本篇将介绍最后一种合成复用原则以及依赖关系传递的三种方式。
合成复用原则
尽量使用合成/聚合的方式,而不是使用继承。
一开始A有两个方法,B正好需要这两个方法,此时最直接的做法就是继承。
package com.wangscaler.compositereuseprinciple;
/**
* @author wangscaler
* @date 2021.06.17 14:50
*/
public class CompositeReusePrinciple {
public static void main(String[] args) {
B b = new B();
b.test();
}
static class A {
void test() {
System.out.println("test");
}
void test1() {
System.out.println("test1");
}
}
static class B extends A {
}
}
这样我们就简单的让B拥有了test和test1的功能,但随着业务的发展,A又新增了test2、test3的方法,这对于B来说是多余的,这大大增加了耦合性。所以依据合成复用原则,修改代码有如下三种方法。
方式一:合成
package com.wangscaler.compositereuseprinciple;
/**
* @author wangscaler
* @date 2021.06.17 14:50
*/
public class CompositeReusePrinciple1 {
public static void main(String[] args) {
B b = new B();
b.test();
}
static class A {
void test() {
System.out.println("test");
}
void test1() {
System.out.println("test1");
}
}
static class B {
A a = new A();
void test() {
a.test();
}
}
}
方式二:依赖
package com.wangscaler.compositereuseprinciple;
/**
* @author wangscaler
* @date 2021.06.17 14:50
*/
public class CompositeReusePrinciple2 {
public static void main(String[] args) {
B b = new B();
b.test(new A());
}
static class A {
void test() {
System.out.println("test");
}
void test1() {
System.out.println("test1");
}
}
static class B {
void test(A a) {
a.test();
}
void test1(A a) {
a.test1();
}
}
}
方式三:聚合
package com.wangscaler.compositereuseprinciple;
/**
* @author wangscaler
* @date 2021.06.17 14:50
*/
public class CompositeReusePrinciple3 {
public static void main(String[] args) {
B b = new B();
b.setA(new A());
b.test();
}
static class A {
void test() {
System.out.println("test");
}
void test1() {
System.out.println("test1");
}
}
static class B {
private A a;
public void setA(A a) {
this.a = a;
}
void test() {
a.test();
}
}
}
总结: 优先考虑合成/聚合,最后考虑继承。聚合组合是一种 “黑箱” 复用,而继承则是白箱,对子类而言都是透明的。
依赖关系传递的三种方式
- 接口传递
- 构造方法传递
- setter方式传递
接口传递
package com.wangscaler.dependencytransfer;
/**
* @author wangscaler
* @date 2021.06.17 17:14
*/
public class DependencyTransfer {
public static void main(String[] args) {
Driver driver = new Driver();
driver.drive(new Civic());
}
interface IDriver {
void drive(ICar car);
}
interface ICar {
void running();
}
static class Civic implements ICar {
public void running() {
System.out.println("思域秒天秒地秒空气");
}
}
static class Driver implements IDriver {
public void drive(ICar car) {
car.running();
}
}
}
在此例中,我们在接口IDriver中传递了ICar,Driver通过实现了IDriver来获取了汽车running的功能
构造方法传递
package com.wangscaler.dependencytransfer;
/**
* @author wangscaler
* @date 2021.06.17 17:14
*/
public class DependencyTransfer1 {
public static void main(String[] args) {
Driver driver = new Driver(new Civic());
driver.drive();
}
interface IDriver {
void drive();
}
interface ICar {
void running();
}
static class Civic implements ICar {
public void running() {
System.out.println("思域秒天秒地秒空气");
}
}
static class Driver implements IDriver {
public ICar car;
public Driver(ICar car) {
this.car = car;
}
public void drive() {
car.running();
}
}
}
和接口传递不同的是,将Icar 作为Driver的成员变量,通过构造器获取Icar。
setter方式传递
package com.wangscaler.dependencytransfer;
/**
* @author wangscaler
* @date 2021.06.17 17:14
*/
public class DependencyTransfer2 {
public static void main(String[] args) {
Driver driver = new Driver();
driver.setCar(new Civic());
driver.drive();
}
interface IDriver {
void drive();
}
interface ICar {
void running();
}
static class Civic implements ICar {
public void running() {
System.out.println("思域秒天秒地秒空气");
}
}
static class Driver implements IDriver {
public ICar car;
public void drive() {
car.running();
}
public void setCar(ICar car) {
this.car = car;
}
}
}
为成员变量ICar,写上Setter方法,将Icar传入。
节外话:不招黑,我思域就是秒天秒地秒空气。
总结
讲到这里,我们的七大原则也就说完了,设计原则的核心三点:一、找出可能变化的地方,将他们提取出来。二、针对接口编程,关注抽象而不关注具体。三、松耦合。
借用语言中文网的一句话:访问加限制,函数要节俭,依赖不允许,动态加接口,父类要抽象,扩展不更改
只是学这些概念,很难灵活的运用,看到这你也许觉着自己学会了,也许你又觉着自己什么都没学会,实践出真知啊,接下来继续跟着我的专栏设计模式一块研究研究设计模式是如何真正的将这些原则用起来,你也许就真的吃透了。