设计模式-七大原则(上篇)
·
1.设计模式的目的
设计模式是为了让程序(软件)具有以下特点:
- 代码重用性
- 可读性
- 可扩展性
- 可靠性(即增加新的功能后对原来的功能没有影响)
- 使程序呈现高内聚,低耦合的特性
2.七大原则
2.1 单一职责原则
2.1.1 基本介绍
即一个类应该只负责一项职责。如类A负责两个不同职责(并不是只能有一个方法),当因为职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2
2.1.2 应用实例
方式1:
public class singleresponsibility1 {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.run("plane");
vehicle.run("car");
}
}
// 方式1:
// 分析:在run中违反了单一职责原则
// 方案:需要根据交通根工具运行方式不同分解为不同类
class Vehicle{
public void run(String vehicle){
if (vehicle == "car"){
System.out.println(vehicle+" run on the road");
}
else if (vehicle == "plane"){
System.out.println(vehicle+" run on the sky");
}
}
}
方式2:
public class singleresponsibility2 {
public static void main(String[] args) {
RoadVehicle roadVehicle = new RoadVehicle();
roadVehicle.run("car");
AirVehicle airVehicle = new AirVehicle();
airVehicle.run("plane");
}
}
// 方法2:
// 分析:遵守了单一职责原则,但是需要将类分解,同时修改客户端(即main中的代码)
// 方案:直接修改Vehicle类
class RoadVehicle{
public void run(String vehicle){
System.out.println(vehicle + " run on the road");
}
}
class AirVehicle{
public void run(String vehicle){
System.out.println(vehicle + " fly on the sky");
}
}
方式3:
public class singleresponsibility3 {
public static void main(String[] args) {
Vehicle2 vehicle2 = new Vehicle2();
vehicle2.runAir("plane");
vehicle2.runRoad("car");
}
}
// 方法3:
// 分析:没有对原来的类进行大的修改。虽然没在类级别上遵循单一职责原则,但是在方法级别上遵循了
class Vehicle2{
public void runAir(String vehicle){
System.out.println(vehicle+" run on the sky");
}
public void runRoad(String vehicle){
System.out.println(vehicle+" run on the road");
}
}
2.1.3 注意事项和细节
- 降低类的复杂度(即一个类只负责一项职责)
- 提高类的可读性和可维护性
- 降低变更引起的风险
- 当类中方法数量足够少时可以在方法级别保持单一职责原则
2.2 接口隔离原则
2.2.1 基本介绍
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
2.2.2 应用实例
下面代码中,Interface1对于A和C而言不是最小接口,B和D必须实现它们不需要的方法
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
class B implements Interface1 {
@Override
public void operation1() {
System.out.println("B实现了operation1");
}
@Override
public void operation2() {
System.out.println("B实现了operation2");
}
@Override
public void operation3() {
System.out.println("B实现了operation3");
}
@Override
public void operation4() {
System.out.println("B实现了operation4");
}
@Override
public void operation5() {
System.out.println("B实现了operation5");
}
}
class D implements Interface1 {
@Override
public void operation1() {
System.out.println("D实现了operation1");
}
@Override
public void operation2() {
System.out.println("D实现了operation2");
}
@Override
public void operation3() {
System.out.println("D实现了operation3");
}
@Override
public void operation4() {
System.out.println("D实现了operation4");
}
@Override
public void operation5() {
System.out.println("D实现了operation5");
}
}
// A类通过接口Integface1依赖(使用)B类,但是只会用到operation1,operation2,operation3方法
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend12(Interface1 i) {
i.operation2();
}
public void depend3(Interface1 i) {
i.operation3();
}
}
// C类通过接口Integface1依赖(使用)D类,但是只会用到operation1,operation4,operation5方法
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend14(Interface1 i) {
i.operation4();
}
public void depend5(Interface1 i) {
i.operation5();
}
}
将Interface1拆分为Interface1,Interface2,Interface3
public static void main(String[] args) {
A a = new A();
// A类通过接口依赖B类
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
C c = new C();
// C类通过接口依赖D类
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}
interface Interface1 {
void operation1();
}
interface Interface2 {
void operation2();
void operation3();
}
interface Interface3 {
void operation4();
void operation5();
}
class B implements Interface1, Interface2 {
@Override
public void operation1() {
System.out.println("B实现了operation1");
}
@Override
public void operation2() {
System.out.println("B实现了operation2");
}
@Override
public void operation3() {
System.out.println("B实现了operation3");
}
}
class D implements Interface1, Interface3 {
@Override
public void operation1() {
System.out.println("D实现了operation1");
}
@Override
public void operation4() {
System.out.println("D实现了operation4");
}
@Override
public void operation5() {
System.out.println("D实现了operation5");
}
}
// A类通过接口Integface1和Interface2依赖(使用)B类
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface2 i) {
i.operation2();
}
public void depend3(Interface2 i) {
i.operation3();
}
}
// C类通过接口Integface1和Interface3依赖(使用)D类
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface3 i) {
i.operation4();
}
public void depend5(Interface3 i) {
i.operation5();
}
}
2.3 依赖倒转原则
2.3.1 基本介绍
- 高层模块不应该依赖低层模块,二者都应该依赖其抽象
- 抽象不应该依赖细节,细节应该依赖抽象(抽象指抽象类或接口,细节就是具体的类)
- 依赖倒转(倒置)的中心思想是面向接口编程
2.3.2 应用实例
方法1:
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
class Email {
public String getInfo() {
return "email info:hello world!";
}
}
// 完成Person接收消息的功能:
// 方式1:简单易实现,但是如果获取的对象是微信不是邮件,则需要新增微信类并且Person类也需要添加相应的方法
// 解决方案: 引入抽象接口IReceiver表示接收者,Person类与该接口发生依赖
// 此时邮件或微信只需要实现该接口即可
class Person {
public void receive(Email email) {
System.out.println(email.getInfo());
}
}
方法2:
public static void main(String[] args) {
// 客户端无需改变
Person person = new Person();
person.receive(new Email());
person.receive(new WeChat());
}
// 定义接口IReceiver
interface IReceiver{
public String getInfo();
}
class Email implements IReceiver{
public String getInfo() {
return "email info:hello world!";
}
}
class WeChat implements IReceiver{
public String getInfo() {
return "WeChat info:hello world!";
}
}
class Person {
// 对类的依赖改为对接口的依赖
public void receive(IReceiver receiver) {
System.out.println(receiver.getInfo());
}
}
2.3.3 注意事项和细节
- 低层模块尽量都要有抽象类或接口,或者两者都有
- 变量的声明类型尽量是抽象类或接口
- 继承时遵循里氏替换原则
- 依赖关系传递的三种方式(即把接口写在哪种方法的参数中):
- 接口传递
- 构造方法传递
- setter方法传递
3.参考
https://www.bilibili.com/video/BV1G4411c7N4?p=5-13
更多推荐
所有评论(0)