目录
文章目录
- 目录
- 七大原则常用于设计模式
- 1.单一职责原则
- 2.接口隔离原则
- 3.依靠倒转原则
- 4.里氏替换原则
- 5.开闭原则
- 6.迪米特法则
- 7.合成复用原则
七大原则常用于设计模式
1.单一职责原则
2.接口隔离原则
3.依靠倒转原则
4.里氏替换原则
5.开闭原则
6.迪米特法则
7.合成复用原则
设计模式的目的
在编写软件的过程中,程序员面临着耦合、内聚性、可维护性、重用性、灵活性等挑战。设计模式是使程序更强大。
- 代码重用性(即不需要多次编写相同功能的代码)
- 可读性(即编程规范,方便其他程序员阅读和理解)
- 可扩展性:(即需要添加新功能时,非常方便,称为可维护)
- 可靠性:(即当我们添加新功能时,对原功能没有影响)
- 使程序具有高内聚和低耦合的特性
1.单一职责原则
基本介绍
对于类别,一个类别应该只负责一个责任。例如,类A负责两种不同的责任:责任1和责任2。当责任1需要改变并改变A时,责任2可能会导致执行错误,因此需要分解类A的粒度A1,A2
应用实例
public class SingleResponsibility {
public static void main(String[] args) {
//方式一 // Vehicle vehicle = new Vehicle(); // vehicle.run("摩托车"); // vehicle.run("汽车"); // vehicle.run("飞机"); //方式二 // RoadVehicle vehicle = new RoadVehicle(); // vehicle.run("摩托车"); // // AirVehicle airVehicle = new AirVehicle(); // airVehicle.run("飞机"); // // WaterVehicle waterVehicle = new WaterVehicle(); // waterVehicle.run("轮船"); //最终 方式三 Vehicle vehicle = new Vehicle(); vehicle.run("小车"); vehicle.runAir("飞机"); vehicle.runWater("轮船"); } } //方法一:违反单一职责原则 //解决方案根据不同的运行方法分解为不同的类别 class Vehicle{
public void run(String vehicle){
System.out.println(vehicle "在公路上运行");
}
//方式三
//修改方法没有对原来的类做大的修改,只是增加方法
//在类上级别遵守单一职责原则,但是方法级别上,仍然是遵守单一职责
public void runAir(String vehicle){
System.out.println(vehicle+"在天空上运行");
}
public void runWater(String vehicle){
System.out.println(vehicle+"在水中行");
}
}
//方式二:
//遵守单一职责原则,但是改动很大,即将类分解,同时修改客户端
class RoadVehicle{
public void run(String vehicle){
System.out.println(vehicle+"公路运行");
}
}
class AirVehicle{
public void run(String vehicle){
System.out.println(vehicle+"天空运行");
}
}
class WaterVehicle{
public void run(String vehicle){
System.out.println(vehicle+"水中运行");
}
}
单一职责原则注意事项和细节
- 降低类的复杂度,一个类只负责一项职责。
- 提高类的可读性,可维护性
- 降低变更引起的风险
- 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则:只有类中方法数量足够少,可以在方法级别保持单一职责原则。
2.接口隔离原则
基本介绍
-
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
-
类A通过接口Interface1依赖类B,类C通过接口Interface1依赖类D,如果接口Interface1对于类A和类C来说不是最小接口,那么类B和类D必须去实现他们不需要的方法。
-
按隔离原则应当这样处理:
拆分为,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
应用实例
public class Segregation1 {
public static void main(String[] args) {
}
}
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");
}
}
class A {
//A 类通过接口Interface1 依赖(使用) B类,但是只会用到1,2,3方法
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface1 i) {
i.operation2();
}
public void depend3(Interface1 i) {
i.operation3();
}
}
class C {
//C 类通过接口Interface1 依赖(使用) D类,但是只会用到1,4,5方法
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface1 i) {
i.operation4();
}
public void depend5(Interface1 i) {
i.operation5();
}
}
应传统方法的问题和使用接口隔离原则改进
- 类A通过Interface1依赖B,类C通过接口Interface1依赖类D,如果接口Interface1对于类A和类C来说不是最小接口,那么类B和类D必须去实现他们不需要的方法
- 将接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
代码实现
public class Segregation1 {
public static void main(String[] args) {
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
C c = new C();
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}
}
//第一步
//接口1
interface Interface1{
void operation1();
}
// 接口2
interface Interface2 {
void operation2();
void operation3();
}
// 接口3
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");
}
}
//第三步
class A {
// A 类通过接口Interface1,Interface2 依赖(使用) B类,但是只会用到1,2,3方法
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface2 i) {
i.operation2();
}
public void depend3(Interface2 i) {
i.operation3();
}
}
class C {
// C 类通过接口Interface1,Interface3 依赖(使用) D类,但是只会用到1,4,5方法
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface3 i) {
i.operation4();
}
public void depend5(Interface3 i) {
i.operation5();
}
}
3.依赖倒转原则
基本介绍
- 高层模块不应该依赖底层模块,二者都应该依赖其抽象
- 依赖倒转(倒置)的中心思想是
- 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类
- 使用的目的是制定好规范,而不涉及任何具体的操作,把去完成
应用实例
public class DependecyInversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
}
class Email{
public String getInfo(){
return "电子邮件信息:hello world";
}
}
//如果我们接受其他对象,则新增类,同时Perons也要增加相应的接受方法
class Person{
public void receive(Email email){
System.out.println(email.getInfo());
}
}
解决方案
引入一个抽象的接口IReceiver,表示接收者,这样Person类与接口IReceiver发生依赖,因为Emali、WeiXin等等属于接收的范围,他们各自实现IReceiver接口。
public class DependecyInversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
person.receive(new WeiXin());
}
}
interface IReceiver{
public String getInfo();
}
class Email implements IReceiver {
@Override
public String getInfo(){
return "电子邮件信息:hello world";
}
}
class WeiXin implements IReceiver{
@Override
public String getInfo() {
return "微信信息:hello world";
}
}
class Person{
public void receive(IReceiver email){
System.out.println(email.getInfo());
}
}
依赖关系传递的三种方式
- 接口传递
- 构造方式传递
- setter方式传递
代码演示
public class DependencyPass {
public static void main(String[] args) {
ChangHong changHong = new ChangHong();
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.open(changHong);
}
}
interface IOpenAndClose{
public void open(ITV tv);
}
interface ITV{
public void play();
}
class ChangHong implements ITV{
@Override
public void play() {
System.out.println("长虹电视机,打开");
}
}
class OpenAndClose implements IOpenAndClose{
@Override
public void open(ITV tv) {
tv.play();
}
}
public class DependencyPass {
public static void main(String[] args) {
ChangHong changHong = new ChangHong();
OpenAndClose openAndClose = new OpenAndClose(changHong);
openAndClose.open();
}
}
// 方式2: 通过构造方法依赖传递
interface IOpenAndClose {
public void open(); //抽象方法
}
interface ITV {
//ITV接口
public void play();
}
class OpenAndClose implements IOpenAndClose {
public ITV tv; //成员
public OpenAndClose(ITV tv) {
//构造器
this.tv = tv;
}
public void open() {
this.tv.play();
}
}
class ChangHong implements ITV {
@Override
public void play() {
// TODO Auto-generated method stub
System.out.println("长虹电视机,打开");
}
}
3.setter方法传递
public class DependencyPass {
public static void main(String[] args) {
ChangHong changHong = new ChangHong();
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.setTv(changHong);
openAndClose.open();
}
}
// 方式2: 通过构造方法依赖传递
interface IOpenAndClose {
public void open(); //抽象方法
public void setTv(ITV tv);
}
interface ITV {
//ITV接口
public void play();
}
class OpenAndClose implements IOpenAndClose {
public ITV tv; //成员
public void open() {
this.tv.play