GitHub源码地址:https://github.com/877148107/java-design-pattern
码云源码地址:https://gitee.com/WilliamWangmy/java-design-pattern
目录
-
什么是设计模式
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
-
设计模式的目的
1)、代码重用性(相同功能的代码,不用多次编写)
2)、可读性(编程规范性,便于其他人的阅读和理解)
3)、可扩展性(当需要增加新的功能时,非常方便)
4)、可靠性(当我们新增功能后对原来的功能没有影响)
5)、程序高内聚、低耦合
-
设计模式类型
设计模式分为三种类型,共23种
1) 创建型模式:
2) 结构型模式:
3) 行为型模式:
模版方法模式 | https://blog.youkuaiyun.com/WMY1230/article/details/105850531 |
命令模式 | https://blog.youkuaiyun.com/WMY1230/article/details/106981218 |
访问者模式 | https://blog.youkuaiyun.com/WMY1230/article/details/106981275 |
迭代器模式 | https://blog.youkuaiyun.com/WMY1230/article/details/106981318 |
观察者模式 | https://blog.youkuaiyun.com/WMY1230/article/details/106981355 |
中介者模式 | |
备忘录模式 | |
解释器模式(Interpreter模式) | |
状态模式 | |
策略模式 | |
职责链模式(责任链模式) |
-
设计模式七大原则
1)、单一职责原则
对类来说的,即一个类应该只负责一项职责。如类A负责两个不同职责:职责1,职责2。当职责1需求变更而改 变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为 A1,A2。
1) 降低类的复杂度,一个类只负责一项职责。
2) 提高类的可读性,可维护性
3) 降低变更引起的风险
4) 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方 法数量足够少,可以在方法级别保持单一职责原则
违反了单一原则
public class SingleResponsibility01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Vehicle vehicle = new Vehicle();
vehicle.run("摩托车");
vehicle.run("汽车");
vehicle.run("飞机");
}
}
/**
* 交通工具类
* 在方的run方法中,违反了单一职责原则.一个类负责了多项职责
*/
class Vehicle {
public void run(String vehicle) {
System.out.println(vehicle + " 在公路上运行....");
}
}
遵循方法级别的单一原则
public class SingleResponsibility03 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Vehicle2 vehicle2 = new Vehicle2();
vehicle2.run("汽车");
vehicle2.runWater("轮船");
vehicle2.runAir("飞机");
}
}
/**
* //方式3的分析
* //1. 这种修改方法没有对原来的类做大的修改,只是增加方法
* //2. 这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责
*/
class Vehicle2 {
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 + " 在水中行....");
}
}
遵循类的单一原则
public class SingleResponsibility02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
RoadVehicle roadVehicle = new RoadVehicle();
roadVehicle.run("摩托车");
roadVehicle.run("汽车");
AirVehicle airVehicle = new AirVehicle();
airVehicle.run("飞机");
}
}
/**
*
方案2的分析
//1. 遵守单一职责原则
//2. 但是这样做的改动很大,即将类分解,同时修改客户端
//3. 改进:直接修改Vehicle 类,改动的代码会比较少=>方案3
*/
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通过接口interface依赖类B,但是A只需要调用类B的实现方法123,类C也通过接口interface依赖类D,但是类C只需要调用类D的实现方法145。因此接口interface对于类A和类C并不是最小接口他们都存在多余的接口方法。类B和类D这里也需要要求实现了他们不需要的方法。这种处理方式并没有遵循接口隔离原则没有达到一个类对另一个类的依赖应该建立在最小的接口上。
没有遵循接口隔离原则
package com.design.pattern.segregation;
/**
* @ClassName: InterfaceSegregation01
* =================================================
* @Description: Java设计模式接口隔离原则
* 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。
* 类B、D实现了接口
* 类A通过接口Interface依赖B类只需要调用类B方法1.2.3;类B多余了方法4.5
* 类C通过接口Interface依赖D类只需要调用类D方法1.4.5;类D多余了方法2.3
* 这里违反了接口隔离原则,没有用到的方法在实现类里面也添加了,改进InterfaceSegregation02
* =================================================
* CreateInfo:
* @Author: William.Wangmy
* @Email: wangmingyong2018@163.com
* @CreateDate: 2020/3/23 22:34
* @Version: V1.0
*/
public class InterfaceSegregation01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
/**
* 接口Interface1有五个方法
*/
interface Interface1 {
/**
* 方法1
*/
void operation1();
/**
* 方法2
*/
void operation2();
/**
* 方法3
*/
void operation3();
/**
* 方法4
*/
void operation4();
/**
* 方法5
*/
void operation5();
}
/**
* 类B实现了接口Interface1
*/
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 类通过接口Interface1 依赖(使用) B类,但是只会用到1,2,3方法
*/
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface1 i) {
i.operation2();
}
public void depend3(Interface1 i) {
i.operation3();
}
}
/**
* C 类通过接口Interface1 依赖(使用) D类,但是只会用到1,4,5方法
*/
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface1 i) {
i.operation4();
}
public void depend5(Interface1 i) {
i.operation5();
}
}
遵循了接口隔离原则
package com.design.pattern.segregation;
/**
* @ClassName: InterfaceSegregation02
* =================================================
* @Description: Java设计模式接口隔离原则
* 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。
* 类Bb实现接口Interface2、Interface3
* 类Dd试下了接口Interface2、Interface4
* 类Aa通过接口Interface依赖Bb类只需要调用类B方法1.2.3
* 类Cc通过接口Interface依赖Dd类只需要调用类D方法1.4.5
* =================================================
* CreateInfo:
* @Author: William.Wangmy
* @Email: wangmingyong2018@163.com
* @CreateDate: 2020/3/23 22:34
* @Version: V1.0
*/
public class InterfaceSegregation02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
// A类通过接口去依赖B类
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
// C类通过接口去依赖(使用)D类
C c = new C();
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}
}
/**
* 接口2
*/
interface Interface2 {
/**
* 方法
*/
void operation1();
}
/**
* 接口3
*/
interface Interface3 {
/**
* 方法2
*/
void operation2();
/**
* 方法3
*/
void operation3();
}
/**
* 接口4
*/
interface Interface4 {
/**
* 方法4
*/
void operation4();
/**
* 方法5
*/
void operation5();
}
/**
* 类Bb实现类Interface2,Interface3
*/
class Bb implements Interface2, Interface3 {
@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");
}
}
/**
* 类Dd实现了接口Interface2,Interface4
*/
class Dd implements Interface2, Interface4 {
@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");
}
}
/**
* 类Aa依赖接口Interface1,Interface1调用方法1.2.3
*/
class Aa {
public void depend1(Interface2 i) {
i.operation1();
}
public void depend2(Interface3 i) {
i.operation2();
}
public void depend3(Interface3 i) {
i.operation3();
}
}
/**
* 类Cc依赖接口Interface1,Interface3调用方法1.4.5
*/
class Cc {
public void depend1(Interface2 i) {
i.operation1();
}
public void depend4(Interface4 i) {
i.operation4();
}
public void depend5(Interface4 i) {
i.operation5();
}
}
3)、依赖倒转原则
依赖倒转原则(Dependence Inversion Principle)是指:
1) 高层模块不应该依赖低层模块,二者都应该依赖其抽象(抽象类或者接口,不要依赖具体的子类)
2) 抽象不应该依赖细节,细节应该依赖抽象
3) 依赖倒转(倒置)的中心思想是面向接口编程
4) 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类
5) 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的 任务交给他们的实现类去完成
没有遵循依赖导致原则导致需要改进的改动量非常大
/**
* @ClassName: DependenceInversion
* =================================================
* @Description: Java设计模式依赖倒置原则
* 依赖倒转原则(Dependence Inversion Principle)是指:
* 1) 高层模块不应该依赖低层模块,二者都应该依赖其抽象(抽象类或者接口,不要依赖具体的子类)
* 2) 抽象不应该依赖细节,细节应该依赖抽象
* 3) 依赖倒转(倒置)的中心思想是面向接口编程
* 4) 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类
* 5) 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的 任务交给他们的实现类去完成
* =================================================
* CreateInfo:
* @Author: William.Wangmy
* @Email: wangmingyong2018@163.com
* @CreateDate: 2020/3/24 21:06
* @Version: V1.0
*/
public class DependenceInversion01 {
public static void main(String[] args) {
//一个person发送邮件
Person person = new Person();
person.send(new Email());
}
}
/**
* 如果一个人也需要发送微信消息的时候,这里又需要建立一个weixin类去发送消息
* 并且person依赖的类也需要改,主程序也需要去改动
* 因此这里没有体现出面向接口编程,person类去依赖了一个具体实现的子类
*/
class Email{
public String sendEmail(){
return "邮件消息:Hello java pattern!";
}
}
class Person{
public void send(Email email){
System.out.println(email.sendEmail());
}
}
遵循依赖导致原则可以对需求进行最小改动量的叠加
public class DependenceInversion02 {
public static void main(String[] args) {
//一个person发送邮件
Person person = new Person();
person.send(new Email());
person.send(new WeiXin());
}
}
/**
* 定义一个消息发送接口
*/
interface ISendMsg{
public String sendMsg();
}
class Email implements ISendMsg{
@Override
public String sendMsg(){
return "邮件消息:Hello java pattern!";
}
}
class WeiXin implements ISendMsg{
@Override
public String sendMsg(){
return "微信消息:Hello java pattern!";
}
}
class Person{
public void send(ISendMsg sendMsg){
System.out.println(sendMsg.sendMsg());
}
}
1.依赖关系传递的三种方式
- 接口传递
- 构造方法传递
- setter方式传递
public class DependenceInversion03 {
public static void main(String[] args) {
//方式一、通过接口传递实现依赖。小米实现了接口ITV01,IOpenAndClose01依赖接口ITV01,OpenAndClose01实现了接口IOpenAndClose01
//然后通过接口IOpenAndClose01依赖接口ITV01调用open方法执行打开电视机操作
XiaoMi xiaoMi = new XiaoMi();
OpenAndClose01 openAndClose01 = new OpenAndClose01();
openAndClose01.open(xiaoMi);
//方式二、通过构造器进行依赖传递。ChangHong实现了接口ITV02,OpenAndClose02通过构造器依赖接口ITV02
//然后调用open方法执行了电视机打开操作
ChangHong changHong = new ChangHong();
OpenAndClose02 openAndClose02 = new OpenAndClose02(changHong);
openAndClose02.open();
//方式三、通过setter方法进行依赖传递。ChuangWei实现了接口ITV03,OpenAndClose03通过setter方法将依赖的接口ITV03传值
//然后调用open方法执行电视机打开操作
ChuangWei chuangWei = new ChuangWei();
OpenAndClose03 openAndClose03 = new OpenAndClose03();
openAndClose03.setTv(chuangWei);
openAndClose03.open();
}
}
/**
* 方式1: 通过接口传递实现依赖
*/
/**
* 开关的接口
*/
interface IOpenAndClose01 {
/**
* 抽象方法,打开接口
* @param tv
*/
void open(ITV01 tv);
}
interface ITV01 {
void play();
}
class XiaoMi implements ITV01 {
@Override
public void play() {
System.out.println("小爱同学打开小米电视");
}
}
/**
* 实现接口
*/
class OpenAndClose01 implements IOpenAndClose01{
@Override
public void open(ITV01 tv){
tv.play();
}
}
/**
* 方式2: 通过构造方法依赖传递
*/
interface IOpenAndClose02 {
/**
* 抽象方法,打开接口
*/
void open();
}
interface ITV02 {
void play();
}
class OpenAndClose02 implements IOpenAndClose02{
/**
* 成员
*/
public ITV02 tv;
/**
* 构造器
* @param tv
*/
public OpenAndClose02(ITV02 tv){
this.tv = tv;
}
@Override
public void open(){
this.tv.play();
}
}
class ChangHong implements ITV02 {
@Override
public void play() {
System.out.println("小爱同学打开长虹电视");
}
}
/**
* 方式3 , 通过setter方法传递
*/
interface IOpenAndClose03 {
void open();
void setTv(ITV03 tv);
}
interface ITV03 {
void play();
}
class OpenAndClose03 implements IOpenAndClose03 {
private ITV03 tv;
@Override
public void setTv(ITV03 tv) {
this.tv = tv;
}
@Override
public void open() {
this.tv.play();
}
}
class ChuangWei implements ITV03 {
@Override
public void play() {
System.out.println("小爱同学打开创维虹电视");
}
}
2.依赖倒转原则的注意事项和细节
1) 低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好.
2) 变量的声明类型尽量是抽象类或接口, 这样我们的变量引用和实际对象间,就存在 一个缓冲层,利于程序扩展和优化
3) 继承时遵循里氏替换原则
4)、里式替代原则
1) 如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1 的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。
2) 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
3) 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题.
类A有基础的继承类C。类B为了重写基础类的方法去继承类A,类A的方法一被类B给重写了。但是当依赖类B去执行方法一的时候并没有执行到类A的方法一。这里类A和类B的耦合性被增强了,原本没有关联的两个类这里被强制关联。这里只需要继承基础类即可。
public class Liskov {
public static void main(String[] args) {
// TODO Auto-generated method stub
A a = new A();
System.out.println("11-3=" + a.func1(11, 3));
System.out.println("1-8=" + a.func1(1, 8));
System.out.println("-----------------------");
B b = new B();
//因为B类不再继承A类,因此调用者,不会再func1是求减法
//调用完成的功能就会很明确
System.out.println("11+3=" + b.func1(11, 3));//这里本意是求出11+3
System.out.println("1+8=" + b.func1(1, 8));// 1+8
System.out.println("11+3+9=" + b.func2(11, 3));
//使用组合仍然可以使用到A类相关方法
System.out.println("11-3=" + b.func3(11, 3));// 这里本意是求出11-3
}
}
//创建一个更加基础的基类
class Base {
//把更加基础的方法和成员写到Base类
}
// A类
class A extends Base {
// 返回两个数的差
public int func1(int num1, int num2) {
return num1 - num2;
}
}
// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends Base {
//如果B需要使用A类的方法,使用组合关系
private A a = new A();
//这里,重写了A类的方法, 可能是无意识
public int func1(int a, int b) {
return a + b;
}
public int func2(int a, int b) {
return func1(a, b) + 9;
}
//我们仍然想使用A的方法
public int func3(int a, int b) {
return this.a.func1(a, b);
}
}
5)、开闭原则
1) 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
2) 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
3) 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
4) 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
违反开闭原则。当对提供者新增一个业务时使用方改动量比较大。这里跟依赖倒置原则类似
package com.design.pattern.openclose;
/**
* @ClassName: OpenClose01
* =================================================
* @Description: Java设计模式开闭原则
* 1) 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
* 2) 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
* 3) 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
* 4) 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
* =================================================
* CreateInfo:
* @Author: William.Wangmy
* @Email: wangmingyong2018@163.com
* @CreateDate: 2020/3/25 22:08
* @Version: V1.0
*/
public class OpenClose01 {
public static void main(String[] args) {
SendMsg sendMsg = new SendMsg();
sendMsg.send(new Email());
sendMsg.send(new WeiXin());
}
}
/**
* 如果需要新增发送手机短信消息,那么提供需要新增一个类
* 使用方也需要新增消息发送的判断和消息发送的代码
* 对于开闭原则来讲 对扩展开放(提供方),对修改关闭(使用方)。 已经不满足此条件,因为使用方的修改已经打开了
* 遵循开闭原则的改进类OpenClose02
*/
/***********以下是使用方***************/
class SendMsg{
public void send(BaseMsg baseMsg){
if (baseMsg.msg_type == 1) {
sendEmail(baseMsg);
}else if(baseMsg.msg_type == 2){
sendWeiXin(baseMsg);
}
}
public void sendEmail(BaseMsg baseMsg){
System.out.println("发送电子邮件。。。。。。。。。。。。。。。。。");
}
public void sendWeiXin(BaseMsg baseMsg){
System.out.println("发送微信消息。。。。。。。。。。。。。。。。。。");
}
}
/***********以下是提供方***************/
/**
* 基类
*/
class BaseMsg{
int msg_type;
}
/**
* 邮件
*/
class Email extends BaseMsg{
Email(){
super.msg_type = 1;
}
}
/**
* 微信
*/
class WeiXin extends BaseMsg{
WeiXin(){
super.msg_type = 2;
}
}
遵循开闭原则,当需要新增一个发送消息的类时,只需要添加一个类继承抽象基础类即可,使用方不用做任何修改
public class OpenClose02 {
public static void main(String[] args) {
SendMsg sendMsg = new SendMsg();
sendMsg.send(new Email());
sendMsg.send(new WeiXin());
sendMsg.send(new Phone());
}
}
/**
* 当需要新增一个发送消息的类时,只需要添加一个类继承抽象基础类即可,使用方不用做任何修改
*/
/***********以下是使用方***************/
class SendMsg{
public void send(BaseMsg baseMsg){
baseMsg.send();
}
}
/***********以下是提供方***************/
/**
* 基类
* 抽象类,提供一个发送消息的抽象方法
*/
abstract class BaseMsg{
int msg_type;
/**
* 发送消息
*/
public abstract void send();
}
/**
* 邮件
*/
class Email extends BaseMsg {
Email(){
super.msg_type = 1;
}
@Override
public void send() {
System.out.println("发送电子邮件。。。。。。。。。。。。。。。。。");
}
}
/**
* 微信
*/
class WeiXin extends BaseMsg {
WeiXin(){
super.msg_type = 2;
}
@Override
public void send() {
System.out.println("发送微信消息。。。。。。。。。。。。。。。。。。");
}
}
/**
* 短信
*/
class Phone extends BaseMsg{
Phone(){
super.msg_type = 3;
}
@Override
public void send() {
System.out.println("发送短信消息。。。。。。。。。。。。。。。。。。");
}
}
6)、迪米特法则
1) 一个对象应该对其他对象保持最少的了解
2) 类与类关系越密切,耦合度越大
3) 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内 部。对外除了提供的public 方法,不对外泄露任何信息
4) 迪米特法则还有个更简单的定义:只与直接的朋友通信
5) 直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。
迪米特法则的核心是降低类之间的耦合 。注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系, 并不是要求完全没有依赖关系
没有遵循迪米特法则
public class Demeter01 {
public static void main(String[] args) {
DepartmentService service = new DepartmentService();
service.printName(new EmployeeService());
}
}
/**
* 员工
*/
class Employee{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 部门
*/
class Department{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 员工处理
* 分析是否遵循迪米特法则(直接朋友关系)
* 1.出现成员变量,方法参数,方法返回值中的类为直接的朋友
* Employee出现在返回值中
*/
class EmployeeService{
public List<Employee> getAllEmployee(){
List<Employee> list = new ArrayList<Employee>();
for (int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setName("员工"+i);
list.add(emp);
}
return list;
}
}
/**
* 部门处理
* 分析是否遵循迪米特法则(直接朋友关系)
* 1.出现成员变量,方法参数,方法返回值中的类为直接的朋友
* Department出现在返回值中
* EmployeeService出现在方法参数中
*
* Employee没有出现在成员变量,方法参数,方法返回值中的类为直接的朋友。因此printName方法中存在没有遵守迪米特法则,改进Demeter02
*/
class DepartmentService{
public List<Department> getAllDepartment(){
List<Department> list = new ArrayList<Department>();
for (int i = 0; i < 5; i++) {
Department dept = new Department();
dept.setName("部门"+i);
list.add(dept);
}
return list;
}
/**
* 打印员工和部门名称
*/
public void printName(EmployeeService employeeService){
System.out.println("打印员工名称。。。。。。。。。。。。。。。");
List<Employee> employees = employeeService.getAllEmployee();
employees.stream().map(employee -> employee.getName()).forEach(System.out::println);
System.out.println("打印部门名称。。。。。。。。。。。。。。。");
List<Department> departments = getAllDepartment();
departments.stream().map(department -> department.getName()).forEach(System.out::println);
}
}
遵循了迪米特法则
public class Demeter02 {
public static void main(String[] args) {
DepartmentService service = new DepartmentService();
service.printName(new EmployeeService());
}
}
/**
* 员工
*/
class Employee{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 部门
*/
class Department{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 员工处理
* 分析是否遵循迪米特法则(直接朋友关系)
* 1.出现成员变量,方法参数,方法返回值中的类为直接的朋友
* Employee出现在返回值中
*/
class EmployeeService{
public List<Employee> getAllEmployee(){
List<Employee> list = new ArrayList<Employee>();
for (int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setName("员工"+i);
list.add(emp);
}
return list;
}
public void printName(){
List<Employee> employees = getAllEmployee();
employees.stream().map(employee -> employee.getName()).forEach(System.out::println);
}
}
/**
* 部门处理
* 分析是否遵循迪米特法则(直接朋友关系)
* 1.出现成员变量,方法参数,方法返回值中的类为直接的朋友
* Department出现在返回值中
* EmployeeService出现在方法参数中
*/
class DepartmentService{
public List<Department> getAllDepartment(){
List<Department> list = new ArrayList<Department>();
for (int i = 0; i < 5; i++) {
Department dept = new Department();
dept.setName("部门"+i);
list.add(dept);
}
return list;
}
/**
* 打印员工和部门名称
*/
public void printName(EmployeeService employeeService){
System.out.println("打印员工名称。。。。。。。。。。。。。。。");
employeeService.printName();
System.out.println("打印部门名称。。。。。。。。。。。。。。。");
List<Department> departments = getAllDepartment();
departments.stream().map(department -> department.getName()).forEach(System.out::println);
}
}
7)、合成复用原则
原则是尽量使用依赖、聚合、组合的方式,而不是使用继承
public class CompositeReuse {
}
class A{
public void operation1(){
System.out.println("方法一。。。。。。。。。。。。。。");
}
public void operation2(){
System.out.println("方法二。。。。。。。。。。。。。。");
}
public void operation3(){
System.out.println("方法三。。。。。。。。。。。。。。");
}
public void operation4(){
System.out.println("方法四。。。。。。。。。。。。。。");
}
}
/**************************类B、C、D、E需要使用类A方法********************************/
/**
* 明显B和A的耦合新增强了
*/
class B extends A{
public void use(){
super.operation1();
}
}
/**
* 类C依赖类A使用其中的方法
*/
class C{
public void user(A a){
a.operation1();
}
}
/**
* 类A聚合到类D使用其中的方法
*/
class D{
private A a;
public void setA(A a) {
this.a = a;
}
public void user(){
this.a.operation1();
}
}
/**
* 类A与类E形成组合关系,使用其中的方法
*/
class E{
public void use(){
A a = new A();
a.operation1();
}
}
-
设计原则核心思想
1) 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代 码混在一起。
2) 针对接口编程,而不是针对实现编程。
3) 为了交互对象之间的松耦合设计而努力
持续学习更新中......