设计模式之七大原则设计模式的七大原则
記憶方法:開接一單里迪合。
1 開閉原則
1.1 簡介
開閉原則的意思是:對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是為了使程序的擴展性好,易于維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類,后面的具體設計中我們會提到這點。
1.2 反面Demo
public class Demo {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
// 新增繪制三角形
graphicEditor.drawShape(new Triangle());
}
}
// 圖形基類
class Shape {
int type;
}
// 繼承Shape的矩形類
class Rectangle extends Shape {
Rectangle() {super.type = 1;}
}
// 繼承Shape的圓形類
class Circle extends Shape {
Circle() {super.type = 2;}
}
// 新增三角形類,繼承Shape類
class Triangle extends Shape {
Triangle() {super.type = 3;}
}
// 繪圖類
class GraphicEditor {
public void drawShape(Shape shape) {
if (shape.type == 1) drawRectangle();
if (shape.type == 2) drawCircle();
// 新增三角形繪制
if (shape.type == 3) drawTriangle();
}
private void drawRectangle() {System.out.println("繪制矩形");}
private void drawCircle() {System.out.println("繪制圓形");}
// 新增繪制三角形方法
private void drawTriangle() {System.out.println("繪制三角形");}
}
1.3 正面Demo
public class Demo {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
// 新增繪制三角形
graphicEditor.drawShape(new Triangle());
}
}
// 圖形基類,抽象類
abstract class Shape {
public abstract void draw();
}
// 矩形類
class Rectangle extends Shape {
@Override
public void draw() {System.out.println("繪制矩形");}
}
// 圓形類
class Circle extends Shape {
@Override
public void draw() {System.out.println("繪制圓形");}
}
// 三角形類
class Triangle extends Shape {
@Override
public void draw() {System.out.println("繪制三角形");}
}
// 繪圖類
class GraphicEditor {
public void drawShape(Shape shape) {
shape.draw();
}
}
2 接口隔離原則
2.1 簡介
這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。它還有另外一個意思是:降低類之間的耦合度。由此可見,其實設計模式就是從大型軟件架構出發、便于升級和維護的軟件設計思想,它強調降低依賴,降低耦合。
2.2 反面Demo
interface Interface1 {
void method1();
void method2();
void method3();
void method4();
void method5();
}
class A implements Interface1{
@Override
public void method1() {
System.out.println("用到method1");
}
@Override
public void method2() {
System.out.println("用到method2");
}
@Override
public void method3() {
System.out.println("用到method3");
}
@Override
public void method4() {}
@Override
public void method5() {}
}
class B implements Interface1{
@Override
public void method1() {
System.out.println("用到method1");
}
@Override
public void method2() {}
@Override
public void method3() {}
@Override
public void method4() {
System.out.println("用到method4");
}
@Override
public void method5() {
System.out.println("用到method5");
}
}
class Test{
public static void main(String[] args) {
Interface1 a = new A();
Interface1 b = new B();
//A用到了1,2,3
a.method1();
a.method2();
a.method3();
//B用到了1,4,5
b.method1();
b.method4();
b.method5();
}
}
2.3 正面Demo
interface Interface1 {
void method1();
}
interface Interface2 {
void method2();
void method3();
}
interface Interface3 {
void method4();
void method5();
}
class A implements Interface1,Interface2{
@Override
public void method1() {
System.out.println("用到method1");
}
@Override
public void method2() {
System.out.println("用到method2");
}
@Override
public void method3() {
System.out.println("用到method3");
}
}
class B implements Interface1,Interface3{
@Override
public void method1() {
System.out.println("用到method1");
}
@Override
public void method4() {
System.out.println("用到method4");
}
@Override
public void method5() {
System.out.println("用到method5");
}
}
class Test{
public static void main(String[] args) {
A a = new A();
B b = new B();
//A用到了1,2,3
a.method1();
a.method2();
a.method3();
//B用到了1,4,5
b.method1();
b.method4();
b.method5();
}
}
3 依賴倒轉原則
3.1 簡介
這個原則是開閉原則的基礎,具體內容:針對接口編程,依賴于抽象而不依賴于具體。
3.2 反例Demo
public class Test {
public static void main(String[] args) {
People people=new People();
people.bug(new Qingcai());
}
}
class People {
public void bug(Qingcai qingcai){
qingcai.run();
}
}
class Qingcai {
public void run(){
System.out.println("買到了青菜");
}
}
3.3 正例Demo
public class Test {
public static void main(String[] args) {
People people=new People();
people.buy(new Qingcai());
people.buy(new Luobo());
}
}
interface Shucai {
void run();
}
class People {
public void buy(Shucai shucai){
shucai.run();
}
}
class Qingcai implements Shucai{
@Override
public void run(){
System.out.println("買到了青菜");
}
}
class Luobo implements Shucai {
@Override
public void run() {
System.out.println("買到了蘿卜");
}
}
4 單一職責原則
4.1 簡介
單一職責原則的基本思想是各司其職,即每個模塊,類或者方法只承擔單個職責,避免多個職責交叉,從而導致修改其中一個職責的時候,影響另外一個職責。
#單一職責的優點:
降低類的復雜度,一個類只負責一項職責。
提高類的可讀性,可維護性。
降低變更引起的風險。
通常情況下,我們應該遵守單一職責原則,只有邏輯足夠簡單,才可以在代碼級別違反單一職責原則:只有當類中方法數量足夠少,可以在方法級別保持單一職責原則。
4.2 反面Demo
public class SingleResponsibilityNegative {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.run("汽車");
vehicle.run("輪船");
vehicle.run("飛機");
}
}
class Vehicle{
public void run(String vehicle){
System.out.println(vehicle+"在公路上跑...");
}
}
4.3 正面Demo
public class SingleResponsibilityPositive {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.run("汽車");
vehicle.runWater("輪船");
vehicle.runAir("飛機");
}
}
class Vehicle{
public void run(String vehicle){
System.out.println(vehicle+"在公路上跑...");
}
public void runWater(String vehicle){
System.out.println(vehicle+"在水上上跑...");
}
public void runAir(String vehicle){
System.out.println(vehicle+"在天上上飛...");
}
}
5 里氏代換原則
5.1 簡介
里氏代換原則是面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。LSP 是繼承復用的基石,只有當派生類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被復用,而派生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。
5.2 反面Demo
public class Test {
public static void main(String[] args) {
A a = new A();
a.run();
System.out.println("將子類替換成父類:");
B b = new B();
b.run();
}
}
class A {
public void run(){
System.out.println("父類執行");
}
}
class B extends A {
public void run(){
System.out.println("子類執行");
}
}
#注:我每次使用子類替換父類的時候,還要擔心這個子類有沒有可能導致問題。此處子類不能直接替換成父類,故沒有遵循里氏替換原則。
5.3 正面Demo1
public class Test {
public static void main(String[] args) {
A a = new A();
a.run();
System.out.println("將子類替換成父類:");
B b = new B();
b.run();
b.runOwn();
}
}
class A {
public void run(){
System.out.println("父類執行");
}
}
class B extends A {
public void runOwn(){
System.out.println("子類執行");
}
}
5.4 正面Demo2
當子類覆蓋或實現父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬松。我們可以發現他并不是重寫,而是方法重載,因為參數不一樣,所以他其實是對繼承的規范化,為了更好的使用繼承。
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
A a = new A();
a.run(new HashMap());
System.out.println("將子類替換成父類:");
B b = new B();
b.run(new HashMap());
}
}
class A {
public void run(HashMap hashMap){
System.out.println("父類執行");
}
}
class B extends A {
public void run(Map map){
System.out.println("子類執行");
}
}
6 迪米特法則,又稱最少知道原則
6.1 簡介
最少知道原則是指:一個實體應當盡量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
6.2 反面Demo
class Computers{
public void closeFile(){
System.out.println("關閉文件");
}
public void closeScreen(){
System.out.println("關閉屏幕");
}
public void powerOff(){
System.out.println("斷電");
}
}
class Person{
private Computers computers;
public void offComputers(){
computers.closeFile();
computers.closeScreen();
computers.powerOff();
}
}
6.2 正面Demo
當用戶關閉電腦時,需要調用計算機的各個方法,但是這些方法的細節太多了,會出現用戶流程出錯,遺漏調用等等,對于用戶來言,他只需要知道關機按鈕就夠了。
class Computers{
public void closeFile(){
System.out.println("關閉文件");
}
public void closeScreen(){
System.out.println("關閉屏幕");
}
public void powerOff(){
System.out.println("斷電");
}
public void offComputers(){
closeFile();
closeScreen();
powerOff();
}
}
class Person{
private Computers computers;
public void offComputers(){
computers.offComputers();
}
}
7 合成復用原則
合成復用原則是指:盡量使用合成/聚合的方式,而不是使用繼承。
總結:七大設計原則已附有相應的正反例,希望對您的學習有幫助,如有需要可以私信我相互學習。
【溫馨提示】
點贊+收藏文章,關注我并私信回復【面試題解析】,即可100%免費領取樓主的所有面試題資料!
總結
以上是生活随笔為你收集整理的设计模式之七大原则设计模式的七大原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 家庭Wifi怎么防止蹭网家里的路由器怎么
- 下一篇: 怎么创建具有真实纹理的CG场景岩石?