文章目录

  • 1. 设计模式有哪些种类
  • 2. 设计模式的目的
  • 3. 设计模式七大原则
    • 3.1. 单一职责原则
      • 1. 基本介绍
      • 2. 模拟场景
    • 2. 接口隔离原则
      • 1. 基本介绍
      • 2. 模拟场景
    • 3. 依赖倒转原则
      • 1. 基本介绍
      • 2. 模拟场景
    • 4. 里氏替换原则
      • 1. 基本介绍
      • 2. 模拟场景
    • 5. 开闭原则
      • 1. 基本介绍
      • 2. 模拟场景
    • 6. 迪米特原则
      • 1. 基本介绍
      • 2. 模拟场景
    • 7. 合成复用原则
      • 1. 基本介绍

1. 设计模式有哪些种类

  1. 创建型模式:提供创建对象的机制,提升已有代码的灵活性和可复用性
  2. 结构性模式:介绍如何将对象和类组装成较大的结构,并保持结构的灵活和高效
  3. 行为模式:介绍对象间的高效沟通和职责传递委派。

2. 设计模式的目的

  编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具有更好的

  • 代码重用性 (即:相同功能的代码,不用多次编写)
  • 可读性 (即:编程规范性, 便于其他程序员的阅读和理解)
  • 可扩展性 (即:当需要增加新的功能时,非常的方便,称为可维护)
  • 可靠性 (即:当我们增加新的功能后,对原来的功能没有影响)
  • 使程序呈现高内聚,低耦合的特性

3. 设计模式七大原则

设计原则核心思想:

  • 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
  • 针对接口编程,而不是针对实现编程。
  • 为了交互对象之间的松耦合设计而努力

3.1. 单一职责原则

1. 基本介绍

  对类来说的,即一个类应该只负责一项职责。如类A负责两个不同职责:职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2

2. 模拟场景

这里通过视频网站例子来说明,当在各视频网站看电影、电视剧,网站针对不同用户类型,网站可以给出不通的反馈。

违背原则方案

public class VideoUserService {//面对频繁迭代的业务需求,这样的代码结构就很难支撑,每一次的实现都可能影响其他逻辑,给整个结果口服务带来不可控的风险public void serveGrade(String userType){if ("VIP用户".equals(userType)){System.out.println("VIP用户,视频1080P蓝光");} else if ("普通用户".equals(userType)){System.out.println("普通用户,视频720P超清");} else if ("访客用户".equals(userType)){System.out.println("访客用户,视频480P高清");}}
}@Test
public void test_serveGrade(){VideoUserService service = new VideoUserService();service.serveGrade("VIP用户");service.serveGrade("普通用户");service.serveGrade("访客用户");}

改善代码

//定义接口
public interface IVideoUserService {// 视频清晰级别;480P、720P、1080Pvoid definition();// 广告播放方式;无广告、有广告void advertisement();}//访客用户
public class GuestVideoUserService implements IVideoUserService {public void definition() {System.out.println("访客用户,视频480P高清");}public void advertisement() {System.out.println("访客用户,视频有广告");}}
//普通用户
public class OrdinaryVideoUserService implements IVideoUserService {public void definition() {System.out.println("普通用户,视频720P超清");}public void advertisement() {System.out.println("普通用户,视频有广告");}}
//VIP用户
public class VipVideoUserService implements IVideoUserService {public void definition() {System.out.println("VIP用户,视频1080P蓝光");}public void advertisement() {System.out.println("VIP用户,视频无广告");}}
//测试
public class ApiTest {@Testpublic void test_VideoUserService(){IVideoUserService guest = new GuestVideoUserService();guest.definition();guest.advertisement();IVideoUserService ordinary = new OrdinaryVideoUserService();ordinary.definition();ordinary.advertisement();IVideoUserService vip = new VipVideoUserService();vip.definition();vip.advertisement();}
}

2. 接口隔离原则

1. 基本介绍

   客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上

2. 模拟场景

违背原则实例

//总接口
interface Interface1 {void operation1();void operation2();void operation3();void operation4();void operation5();
}class B implements Interface1 {public void operation1() {System.out.println("B 实现了 operation1");}public void operation2() {System.out.println("B 实现了 operation2");}public void operation3() {System.out.println("B 实现了 operation3");}public void operation4() {System.out.println("B 实现了 operation4");}public void operation5() {System.out.println("B 实现了 operation5");}
}class D implements Interface1 {public void operation1() {System.out.println("D 实现了 operation1");}public void operation2() {System.out.println("D 实现了 operation2");}public void operation3() {System.out.println("D 实现了 operation3");}public void operation4() {System.out.println("D 实现了 operation4");}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();}
}

改善代码UML图

3. 依赖倒转原则

1. 基本介绍

依赖倒转原则(Dependence Inversion Principle)是指:

  • 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 依赖倒转(倒置)的中心思想是面向接口编程
  • 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多
  • 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

2. 模拟场景

比如某互联网举办抽奖活动,抽奖活动的方式会随机变化的,比如随机抽奖、权重抽奖等。

违反原则方案

//投注用户
public class BetUser {private String userName;  // 用户姓名private int userWeight;   // 用户权重public BetUser() {}public BetUser(String userName, int userWeight) {this.userName = userName;this.userWeight = userWeight;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public int getUserWeight() {return userWeight;}public void setUserWeight(int userWeight) {this.userWeight = userWeight;}
}
//抽奖方式
public class DrawControl {// 随机public List<BetUser> doDrawRandom(List<BetUser> list, int count) {// 集合数量很小直接返回if (list.size() <= count) return list;// 乱序集合Collections.shuffle(list);// 取出指定数量的中奖用户List<BetUser> prizeList = new ArrayList<>(count);for (int i = 0; i < count; i++) {prizeList.add(list.get(i));}return prizeList;}// 权重public List<BetUser> doDrawWeight(List<BetUser> list, int count) {// 按照权重排序list.sort((o1, o2) -> {int e = o2.getUserWeight() - o1.getUserWeight();if (0 == e) return 0;return e > 0 ? 1 : -1;});// 取出指定数量的中奖用户List<BetUser> prizeList = new ArrayList<>(count);for (int i = 0; i < count; i++) {prizeList.add(list.get(i));}return prizeList;}}//测试@Test
public void test_DrawControl(){List<BetUser> betUserList = new ArrayList<>();betUserList.add(new BetUser("花花", 65));betUserList.add(new BetUser("豆豆", 43));betUserList.add(new BetUser("小白", 72));betUserList.add(new BetUser("笨笨", 89));betUserList.add(new BetUser("丑蛋", 10));DrawControl drawControl = new DrawControl();List<BetUser> prizeRandomUserList = drawControl.doDrawRandom(betUserList, 3);logger.info("随机抽奖,中奖用户名单:{}", JSON.toJSON(prizeRandomUserList));List<BetUser> prizeWeightUserList = drawControl.doDrawWeight(betUserList, 3);logger.info("权重抽奖,中奖用户名单:{}", JSON.toJSON(prizeWeightUserList));}

这样的实现方式扩展起来很麻烦,最后代码行数越多,不好维护

改善代码

//抽奖接口
public interface IDraw {// 获取中奖用户接口List<BetUser> prize(List<BetUser> list, int count);}//随机抽奖实现
public class DrawRandom implements IDraw {@Overridepublic List<BetUser> prize(List<BetUser> list, int count) {// 集合数量很小直接返回if (list.size() <= count) return list;// 乱序集合Collections.shuffle(list);// 取出指定数量的中奖用户List<BetUser> prizeList = new ArrayList<>(count);for (int i = 0; i < count; i++) {prizeList.add(list.get(i));}return prizeList;}}//权重抽奖
public class DrawWeightRank implements IDraw {@Overridepublic List<BetUser> prize(List<BetUser> list, int count) {// 按照权重排序list.sort((o1, o2) -> {int e = o2.getUserWeight() - o1.getUserWeight();if (0 == e) return 0;return e > 0 ? 1 : -1;});// 取出指定数量的中奖用户List<BetUser> prizeList = new ArrayList<>(count);for (int i = 0; i < count; i++) {prizeList.add(list.get(i));}return prizeList;}}//调用控制器
public class DrawControl {private IDraw draw;public List<BetUser> doDraw(IDraw draw, List<BetUser> betUserList, int count) {return draw.prize(betUserList, count);}}//
@Test
public void test_DrawControl() {List<BetUser> betUserList = new ArrayList<>();betUserList.add(new BetUser("花花", 65));betUserList.add(new BetUser("豆豆", 43));betUserList.add(new BetUser("小白", 72));betUserList.add(new BetUser("笨笨", 89));betUserList.add(new BetUser("丑蛋", 10));DrawControl drawControl = new DrawControl();List<BetUser> prizeRandomUserList = drawControl.doDraw(new DrawRandom(), betUserList, 3);logger.info("随机抽奖,中奖用户名单:{}", JSON.toJSON(prizeRandomUserList));List<BetUser> prizeWeightUserList = drawControl.doDraw(new DrawWeightRank(), betUserList, 3);logger.info("权重抽奖,中奖用户名单:{}", JSON.toJSON(prizeWeightUserList));}

4. 里氏替换原则

1. 基本介绍

  • 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法。
  • 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题。.

2. 模拟场景

假设在构建银行系统是,储蓄卡是第一类,信用卡是第二类,为了让信用卡可以使用储蓄卡额一些方法,选择信用卡继承储蓄卡。

违背原则方案

//储蓄卡
public class CashCard {private Logger logger = LoggerFactory.getLogger(CashCard.class);/*** 提现** @param orderId 单号* @param amount  金额* @return 状态码 0000成功、0001失败、0002重复*/public String withdrawal(String orderId, BigDecimal amount) {// 模拟支付成功logger.info("提现成功,单号:{} 金额:{}", orderId, amount);return "0000";}/*** 储蓄** @param orderId 单号* @param amount  金额*/public String recharge(String orderId, BigDecimal amount) {// 模拟充值成功logger.info("储蓄成功,单号:{} 金额:{}", orderId, amount);return "0000";}/*** 交易流水查询* @return 交易流水*/public List<String> tradeFlow() {logger.info("交易流水查询成功");List<String> tradeList = new ArrayList<String>();tradeList.add("100001,100.00");tradeList.add("100001,80.00");tradeList.add("100001,76.50");tradeList.add("100001,126.00");return tradeList;}}
//信用卡public class CreditCard extends CashCard {private Logger logger = LoggerFactory.getLogger(CashCard.class);@Overridepublic String withdrawal(String orderId, BigDecimal amount) {// 校验if (amount.compareTo(new BigDecimal(1000)) >= 0){logger.info("贷款金额校验(限额1000元),单号:{} 金额:{}", orderId, amount);return "0001";}// 模拟生成贷款单logger.info("生成贷款单,单号:{} 金额:{}", orderId, amount);// 模拟支付成功logger.info("贷款成功,单号:{} 金额:{}", orderId, amount);return "0000";}@Overridepublic String recharge(String orderId, BigDecimal amount) {// 模拟生成还款单logger.info("生成还款单,单号:{} 金额:{}", orderId, amount);// 模拟还款成功logger.info("还款成功,单号:{} 金额:{}", orderId, amount);return "0000";}@Overridepublic List<String> tradeFlow() {return super.tradeFlow();}}//测试@Testpublic void test_CashCard() {CashCard cashCard = new CashCard();// 提现cashCard.withdrawal("100001", new BigDecimal(100));// 储蓄cashCard.recharge("100001", new BigDecimal(100));// 交易流水List<String> tradeFlow = cashCard.tradeFlow();logger.info("查询交易流水,{}", JSON.toJSONString(tradeFlow));}@Testpublic void test_CreditCard() {CreditCard creditCard = new CreditCard();// 支付creditCard.withdrawal("100001", new BigDecimal(100));// 还款creditCard.recharge("100001", new BigDecimal(100));// 交易流水List<String> tradeFlow = creditCard.tradeFlow();logger.info("查询交易流水,{}", JSON.toJSONString(tradeFlow));}

这种集成复用了父类核心功能,但也破环了原有的方法。

改善代码

储蓄卡和信用卡在功能使用上有很多类似,可以将共同的属性及逻辑提取出一个抽象类,由抽象类定义所有卡的共同核心属性、逻辑。

//抽象银行卡类
public abstract class BankCard {private Logger logger = LoggerFactory.getLogger(BankCard.class);private String cardNo;   // 卡号private String cardDate; // 开卡时间public BankCard(String cardNo, String cardDate) {this.cardNo = cardNo;this.cardDate = cardDate;}abstract boolean rule(BigDecimal amount);// 正向入账,+ 钱public String positive(String orderId, BigDecimal amount) {// 入款成功,存款、还款logger.info("卡号{} 入款成功,单号:{} 金额:{}", cardNo, orderId, amount);return "0000";}// 逆向入账,- 钱public String negative(String orderId, BigDecimal amount) {// 入款成功,存款、还款logger.info("卡号{} 出款成功,单号:{} 金额:{}", cardNo, orderId, amount);return "0000";}/*** 交易流水查询** @return 交易流水*/public List<String> tradeFlow() {logger.info("交易流水查询成功");List<String> tradeList = new ArrayList<String>();tradeList.add("100001,100.00");tradeList.add("100001,80.00");tradeList.add("100001,76.50");tradeList.add("100001,126.00");return tradeList;}public String getCardNo() {return cardNo;}public String getCardDate() {return cardDate;}
}//模拟储蓄卡功能
public class CashCard extends BankCard {private Logger logger = LoggerFactory.getLogger(CashCard.class);public CashCard(String cardNo, String cardDate) {super(cardNo, cardDate);}boolean rule(BigDecimal amount) {return true;}/*** 提现** @param orderId 单号* @param amount  金额* @return 状态码 0000成功、0001失败、0002重复*/public String withdrawal(String orderId, BigDecimal amount) {// 模拟支付成功logger.info("提现成功,单号:{} 金额:{}", orderId, amount);return super.negative(orderId, amount);}/*** 储蓄** @param orderId 单号* @param amount  金额*/public String recharge(String orderId, BigDecimal amount) {// 模拟充值成功logger.info("储蓄成功,单号:{} 金额:{}", orderId, amount);return super.positive(orderId, amount);}/*** 风险校验** @param cardNo  卡号* @param orderId 单号* @param amount  金额* @return 状态*/public boolean checkRisk(String cardNo, String orderId, BigDecimal amount) {// 模拟风控校验logger.info("风控校验,卡号:{} 单号:{} 金额:{}", cardNo, orderId, amount);return true;}}//信用卡
public class CreditCard extends CashCard {private Logger logger = LoggerFactory.getLogger(CreditCard.class);public CreditCard(String cardNo, String cardDate) {super(cardNo, cardDate);}boolean rule2(BigDecimal amount) {return amount.compareTo(new BigDecimal(1000)) <= 0;}/*** 提现,信用卡贷款** @param orderId 单号* @param amount  金额* @return 状态码*/public String loan(String orderId, BigDecimal amount) {boolean rule = rule2(amount);if (!rule) {logger.info("生成贷款单失败,金额超限。单号:{} 金额:{}", orderId, amount);return "0001";}// 模拟生成贷款单logger.info("生成贷款单,单号:{} 金额:{}", orderId, amount);// 模拟支付成功logger.info("贷款成功,单号:{} 金额:{}", orderId, amount);return super.negative(orderId, amount);}/*** 还款,信用卡还款** @param orderId 单号* @param amount  金额* @return 状态码*/public String repayment(String orderId, BigDecimal amount) {// 模拟生成还款单logger.info("生成还款单,单号:{} 金额:{}", orderId, amount);// 模拟还款成功logger.info("还款成功,单号:{} 金额:{}", orderId, amount);return super.positive(orderId, amount);}}
//test@Test
public void test_bankCard() {logger.info("里氏替换前,CashCard类:");CashCard bankCard = new CashCard("6214567800989876", "2020-10-01");// 提现bankCard.withdrawal("100001", new BigDecimal(100));// 储蓄bankCard.recharge("100001", new BigDecimal(100));logger.info("里氏替换后,CreditCard类:");CashCard creditCard = new CreditCard("6214567800989876", "2020-10-01");// 提现creditCard.withdrawal("100001", new BigDecimal(1000000));// 储蓄creditCard.recharge("100001", new BigDecimal(100));}@Testpublic void test_CreditCard(){CreditCard creditCard = new CreditCard("6214567800989876", "2020-10-01");// 支付,贷款creditCard.loan("100001", new BigDecimal(100));// 还款creditCard.repayment("100001", new BigDecimal(100));}

5. 开闭原则

1. 基本介绍

  • 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  • 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

2. 模拟场景

对于外部的调用方来说,只要能体现出面向抽象编程,定义出接口并实现其方法,即不修改原有方法体,只通过继承方式进行扩展,都可以体现出开闭原则。

这里计算三种形状的面积,其中⚪型面积Π是3.14,但后续由于Π值取的精度对于某些场景不足,需要扩展

//接口
public interface ICalculationArea {/*** 计算面积,长方形** @param x 长* @param y 宽* @return 面积*/double rectangle(double x, double y);/*** 计算面积,三角形* @param x 边长x* @param y 边长y* @param z 边长z* @return  面积** 海伦公式:S=√[p(p-a)(p-b)(p-c)] 其中:p=(a+b+c)/2*/double triangle(double x, double y, double z);/*** 计算面积,圆形* @param r 半径* @return 面积** 圆面积公式:S=πr²*/double circular(double r);}// Π =3.14
public class CalculationArea implements ICalculationArea {private final static double π = 3.14D;public double rectangle(double x, double y) {return x * y;}public double triangle(double x, double y, double z) {double p = (x + y + z) / 2;return Math.sqrt(p * (p - x) * (p - y) * (p - z));}public double circular(double r) {return π * r * r;}}//违背原则,如果不考虑开闭原则直接修改实现类的Π值,但这样做会破环稳定性,可以追加一个实现类,只修改Π的值
public class CalculationAreaExt extends CalculationArea {private final static double π = 3.141592653D;@Overridepublic double circular(double r) {return π * r * r;}}

6. 迪米特原则

1. 基本介绍

  • 一个对象应该对其他对象保持最少的了解
  • 类与类关系越密切,耦合度越大
  • 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public 方法,不对外泄露任何信息

2. 模拟场景

本例通过学生、老师、校长关系来说明

违背原则

//学生
public class Student {private String name;    // 学生姓名private int rank;       // 考试排名(总排名)private double grade;   // 考试分数(总分)public Student() {}public Student(String name, int rank, double grade) {this.name = name;this.rank = rank;this.grade = grade;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getRank() {return rank;}public void setRank(int rank) {this.rank = rank;}public double getGrade() {return grade;}public void setGrade(double grade) {this.grade = grade;}
}
//老师
public class Teacher {private String name;                // 老师名称private String clazz;               // 班级private static List<Student> studentList;  // 学生public Teacher() {}public Teacher(String name, String clazz) {this.name = name;this.clazz = clazz;}static {studentList = new ArrayList<>();studentList.add(new Student("花花", 10, 589));studentList.add(new Student("豆豆", 54, 356));studentList.add(new Student("秋雅", 23, 439));studentList.add(new Student("皮皮", 2, 665));studentList.add(new Student("蛋蛋", 19, 502));}public static List<Student> getStudentList() {return studentList;}public String getName() {return name;}public String getClazz() {return clazz;}
}
//校长
public class Principal {private Teacher teacher = new Teacher("丽华", "3年1班");// 查询班级信息,总分数、学生人数、平均值public Map<String, Object> queryClazzInfo(String clazzId) {// 获取班级信息;学生总人数、总分、平均分int stuCount = clazzStudentCount();double totalScore = clazzTotalScore();double averageScore = clazzAverageScore();// 组装对象,实际业务开发会有对应的类Map<String, Object> mapObj = new HashMap<>();mapObj.put("班级", teacher.getClazz());mapObj.put("老师", teacher.getName());mapObj.put("学生人数", stuCount);mapObj.put("班级总分数", totalScore);mapObj.put("班级平均分", averageScore);return mapObj;}// 总分public double clazzTotalScore() {double totalScore = 0;for (Student stu : teacher.getStudentList()) {totalScore += stu.getGrade();}return totalScore;}// 平均分public double clazzAverageScore(){double totalScore = 0;for (Student stu : teacher.getStudentList()) {totalScore += stu.getGrade();}return totalScore / teacher.getStudentList().size();}// 班级人数public int clazzStudentCount(){return teacher.getStudentList().size();}}//test 因为校长需要了解每个同学的信息,如果所有的班级都要校长来统计,代码会很臃肿,也不易扩展
public class ApiTest {private Logger logger = LoggerFactory.getLogger(ApiTest.class);@Testpublic void test_Principal() {Principal principal = new Principal();Map<String, Object> map = principal.queryClazzInfo("3年1班");logger.info("查询结果:{}", JSON.toJSONString(map));}}

改善代码

public class Teacher {private String name;                // 老师名称private String clazz;               // 班级private static List<Student> studentList;  // 学生public Teacher() {}public Teacher(String name, String clazz) {this.name = name;this.clazz = clazz;}static {studentList = new ArrayList<>();studentList.add(new Student("花花", 10, 589));studentList.add(new Student("豆豆", 54, 356));studentList.add(new Student("秋雅", 23, 439));studentList.add(new Student("皮皮", 2, 665));studentList.add(new Student("蛋蛋", 19, 502));}// 总分public double clazzTotalScore() {double totalScore = 0;for (Student stu : studentList) {totalScore += stu.getGrade();}return totalScore;}// 平均分public double clazzAverageScore(){double totalScore = 0;for (Student stu : studentList) {totalScore += stu.getGrade();}return totalScore / studentList.size();}// 班级人数public int clazzStudentCount(){return studentList.size();}public String getName() {return name;}public String getClazz() {return clazz;}
}//老师
public class Principal {private Teacher teacher = new Teacher("丽华", "3年1班");// 查询班级信息,总分数、学生人数、平均值public Map<String, Object> queryClazzInfo(String clazzId) {// 获取班级信息;学生总人数、总分、平均分int stuCount = teacher.clazzStudentCount();double totalScore = teacher.clazzTotalScore();double averageScore = teacher.clazzAverageScore();// 组装对象,实际业务开发会有对应的类Map<String, Object> mapObj = new HashMap<>();mapObj.put("班级", teacher.getClazz());mapObj.put("老师", teacher.getName());mapObj.put("学生人数", stuCount);mapObj.put("班级总分数", totalScore);mapObj.put("班级平均分", averageScore);return mapObj;}}//test@Test
public void test_Principal() {Principal principal = new Principal();Map<String, Object> map = principal.queryClazzInfo("3年1班");logger.info("查询结果:{}", JSON.toJSONString(map));}

7. 合成复用原则

1. 基本介绍

原则是尽量使用合成/聚合的方式,而不是使用继承

设计模式七大原则介绍相关推荐

  1. Java面试之设计模式七大原则

    最近项目不太忙,不怎么加班,正利用晚上时间好好学习学习设计模式,之前可能多多少少都用到过,但是有些还是很模糊,这下正好系统的学一下. 好了,话不多说,进入正题. 1.什么是设计模式? 软件工程中,设计 ...

  2. 第 2 章 设计模式七大原则

    第 2 章 设计模式七大原则 1.设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战, 设计模式是为了让程序(软件),具有如下更好的 ...

  3. 设计模式——七大原则

    设计模式--七大原则 汇总篇 1.单一职责 2.接口隔离 3.依赖倒转 4.里氏代换原则 5.开闭原则 6.迪米特法则 7.合成复用 汇总篇 1.单一职责 对类来说的,即一个类应该只负责一项职责.如类 ...

  4. 图解设计模式-设计模式七大原则

    Java设计模式 设计模式七大原则 设计模式的目的 编写软件过程中,程序员面临来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让 **程序(软件)**具有更好的 ...

  5. Day305.设计模式七大原则 -Java设计模式

    七大设计原则 一.设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具有更好的↓↓↓ 1. 代码重用 ...

  6. Java设计模式七大原则-单一职责原则

    目录 概述:设计模式的目的 设计模式七大原则 单一职责原则 单一职责原则注意事项和细节 概述:设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等 ...

  7. 设计模式七大原则知识概括

    设计模式七大原则知识概括 设计模式的目的 设计模式七大原则 单一职责原则 接口隔离原则 依赖倒转(倒置)原则 里氏替换原则 开闭原则 迪米特法则 合成复用原则 设计原则核心思想 设计模式的目的 目的: ...

  8. 备战面试日记(3.1) - (设计模式.七大原则)

    本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.4 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文章 ...

  9. 设计模式——七大原则(附代码示例)

    一. 设计模式概念         对接口编程而不是对实现编程:优先使用对象组合而不是继承 二. 设计模式总览 1. 创建型模式(Creational Patterns):(5) 单例(Singlet ...

最新文章

  1. MyBatis if标签的用法
  2. UML 中各种图形重要性的排行
  3. 数据结构与算法 | 二分查找
  4. html输入支付密码样式,基于JS实现类似支付宝支付密码输入框
  5. 内推学弟进了腾讯,看看他的标杆简历!
  6. python矩阵赋值提高速度_Numpy大规模矩阵运算优化加速技巧
  7. python老师 课时费_花10分钟写一个Python脚本,搞定了初中老师一下午的工作
  8. OSAL启动过程分析
  9. Matlab 网络通信(TCP IP)
  10. java计算机毕业设计网上拍卖系统源码+数据库+系统+lw文档+mybatis+运行部署
  11. 20191129每周精品之编程
  12. dell台式机安装centos7网卡设置
  13. 计算机组成原理相关知识重要吗?
  14. Eclipse Xtend - 疯狂的Java10
  15. pr预设的卷及内核锐化是什么_PR CC 特效
  16. POJ 3164 Command Network(朱刘算法)
  17. 跨考计算机面试英语自我介绍,2019考研复试面试英语自我介绍范文(2)
  18. 付费代理IP——Redis数据库的安装
  19. 【学习笔记】Spring-IOC-DI-AOP 学习笔记
  20. telnet测试server的使用

热门文章

  1. 国家普通话水平测试官方软件,国家普通话水平测试题
  2. 一个笨拙的前段学习者的第一次博客
  3. 李开复写给中国大学生的七封信(1/7)
  4. 英伟达驱动安装(华为makebook13-2018 NVIDIA-GeForce-MX150)
  5. unity进行发布html,unity发布网页版(内嵌网页)
  6. 麻将胡牌算法——C#
  7. EMC常见术语-dB、dBm、dBw以及如何计算
  8. SylixOS 经得起检验的国产操作系统 (一)
  9. 现在完成时、过去完成时、完成进行时
  10. 吃透一切整流滤波电路(转)