《大话设计模式》 阅读梳理(设计模式详解)

设计模式的优点

合理的使用设计模式来开发程序,可以有效地提高代码的复用性,可维护性,灵活性,扩展性。

简单工厂模式

实现一个计算器,可以进行±*/运算。用工厂来生成相应的计算对象。

//主类
package com.sea;

import java.util.Scanner;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
public class Calculator {
   
    public static void main(String[] args) {
   
        Operation operation;
        Scanner input = new Scanner(System.in);
        System.out.println("请输入你要进行的运算方式(+-*/)");
        String symbol = input.next();
        operation = OperationFactory.creatOperation(symbol);
        System.out.println("输入运算数");
        double numA = input.nextDouble();
        double numB = input.nextDouble();
        try {
   
            double result = operation.getResult(numA, numB);
            System.out.println("result = "+result);
        } catch (Exception e) {
   
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
}


//计算对象类 其中Operation为父类,里面定义了计算数和一个getResult方法。其他子类来实现这个方法。(继承)
package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
public abstract class Operation {
   
    private double numA;
    private double numB;

    public abstract double getResult(double numA,double numB) throws Exception;
    public double getNumA() {
   
        return numA;
    }

    public void setNumA(double numA) {
   
        this.numA = numA;
    }

    public double getNumB() {
   
        return numB;
    }

    public void setNumB(double numB) {
   
        this.numB = numB;
    }
}
class OperationAdd extends Operation{
   

    @Override
    public double getResult(double numA, double numB) {
   
        return numA+numB;
    }
}
class OperationSubtraction extends Operation{
   

    @Override
    public double getResult(double numA, double numB) {
   
        return numA-numB;
    }
}
class OperationMultiplication extends Operation{
   

    @Override
    public double getResult(double numA, double numB) {
   
        return numA*numB;
    }
}
class OperationDivision extends Operation{
   

    @Override
    public double getResult(double numA, double numB) throws Exception {
   
        if(numB==0)
            throw new Exception("除数不能为0");
        return numA/numB;
    }
}


//工厂类,根据输入的符号来生成相应的对象。(多态)
package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
public class OperationFactory {
   
    public static Operation creatOperation(String symbol){
   
        Operation operation = null;
        switch (symbol){
   
            case "+" :
                operation = new OperationAdd();
                break;
            case "-" :
                operation = new OperationSubtraction();
                break;
            case "*" :
                operation = new OperationMultiplication();
                break;
            case "/" :
                operation = new OperationDivision();
                break;
        }
        return operation;
    }
}

在这里插入图片描述

工厂模式可以将一些具有相同父类的对象的创建过程集中到一起。将对象的创建和使用分隔开。大大增加了程序可扩展性并且更加利于维护。当你需要更改/添加对象的实现类时,只需要更改工厂即可。而不必去每一个用到该对象的地方做修改。

策略模式

实现一个商场收银台功能,当商场进行不同的促销活动时,将商品价格转换成实际要支付的价格。
策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
在这里插入图片描述

package com.sea;

import java.util.Scanner;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
//收银台主类
public class Cashier {
   
    public static void main(String[] args) {
   
        PayMoneyContext context = null;
        System.out.println("选择销售策略");
        System.out.println("1.正常出售");
        System.out.println("2.打8折出售");
        System.out.println("3.满500返200");
        Scanner input = new Scanner(System.in);
        int type = input.nextInt();
        context = new PayMoneyContext(type);
        System.out.println("输入购买商品总价值");
        double money = input.nextDouble();
        System.out.println("实际需要支付:"+context.getResult(money));
    }
}

package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
//付钱算法父类
public abstract class PayMoney {
   
    public abstract double payMoneyAlgorithm(Double money) ;
}
//正常的付钱算法
class NormalAlgorithm extends  PayMoney{
   

    @Override
    public double payMoneyAlgorithm(Double money) {
   
        return money;
    }
}
//打折付钱算法
class DiscountAlgorithm extends  PayMoney{
   
    private double proportion = 1;
    public DiscountAlgorithm(double proportion){
   
        this.proportion = proportion;
    }
    @Override
    public double payMoneyAlgorithm(Double money) {
   
        return money*proportion;
    }
}
//返利付钱算法
class RebateAlgorithm extends  PayMoney{
   
    private double critical = Double.MAX_VALUE;//临界值,到达这个值才会返利
    private double rebate = 0;
    public RebateAlgorithm(double critical,double rebate){
   
        this.critical = critical;
        this.rebate = rebate;
    }
    @Override
    public double payMoneyAlgorithm(Double money) {
   
        if(money>=critical){
   
            return money-rebate;
        }else
        return money;
    }
}

package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
//类略类
public class PayMoneyContext {
   
    private PayMoney payMoney = null;
    public PayMoneyContext(int type){
   
        switch (type){
   
            case 1://1.正常出售
                payMoney = new NormalAlgorithm();
                break;
            case 2://2.8折出售
                payMoney = new DiscountAlgorithm(0.8);
                break;
            case 3://3.500200
                payMoney = new RebateAlgorithm(500,200);
        }
    }
    public double getResult(double money){
   
        return payMoney.payMoneyAlgorithm(money);
    }
}

在这里插入图片描述

策略模式与工厂模式在结构上有点类似。不过工厂类只负责生产对象,具体的方法调用还需要调用者进行调用。并且调用者需要既知道工厂类,也需要认识工厂创建的实例。而策略模式中,调用者只需要认识策略类即可,甚至都不需要知道具体是哪个类调用的业务方法。在策略类中可以用简单工厂模式生成对象,并在对调用者开放的方法中实现具体对象的方法调用,而不在需要调用者再去主动调用。再一次降低了耦合度。

单一职责原则

单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。
如果一个类承担过多的责任,那么就相当于这些功能高度耦合在一起。当更改其中一个功能时,可能导致其他正常运行的功能发生不可预知的错误。单一职责原则是高内聚低耦合的体现。

开放——封闭原则

开放——封闭原则是说软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。
这就需要我们对功能做抽象处理。比如,一块木板能用来干什么呢?可以用来制作桌子,椅子,床等等。如果不适用开放——封闭原则,我们会怎么做呢?
最开始木板只能用来制作桌子。


public interface BoardInterface {
   
    void makingTable();
}


public class Board implements BoardInterface {
   
    @Override
    public void makingTable() {
   
        System.out.println("制作桌子的流程");
    }
}

此时如果要增加新的需求怎么办呢?直接在接口中添加方法,然后再在实现类中实现方法不就行了么?但是这样写的代码既不灵活,难以维护,不好扩展,复用性差。这样写就完全不符合开放——封闭原则。增加需求要尽量用增加代码来解决(增加类)而不是修改之前的类。要尽量做到类一旦设计好就不再更改。因此应该改为

package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
public interface BoardInterface {
   
    void making();
}


package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
public class BedBoard implements BoardInterface {
   
    @Override
    public void making() {
   
        System.out.println("制作床的流程");
    }
}

package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
public class CharBoard implements BoardInterface {
   
    @Override
    public void making() {
   
        System.out.println("制作椅子的流程");
    }
}

package com.sea;

/**
 * @Auther: Maple
 * @Date: 2020/10/15
 */
public class TableBoard implements BoardInterface {
   
    @Override
    public void making() {
   
        System.out.println("制作桌子的流程");
    }
}

如果需要为这个木板增加新的业务,只需要添加新的类即可。

里氏代换原则

里氏代换缓则:子类型必须能够替换掉他们的父类型。
如果此时有一个动物类,他里面有跑 跳 吃 喝方法。那么当要设计一个鱼类时能不能继承这个动物类呢。根据里氏代换原则是不能的。因为鱼并不能跑与跳。因此子类并不能够替换掉他们的父类。

依赖倒转原则

高层模块不应该依赖底层模块。两个都应该依赖抽象。
抽象不应该依赖细节。细节应该依赖抽象。
高层模块如果直接依赖底层模块的话,如果要更换底层模块,那么即使高层模块的逻辑不需要改变,高层模块也不能复用了。这显然不是我们想要的。
如果高层模块与底层模块都是依赖于接口的就不同了。高层模块只关心接口包含哪些功能,而不必关心具体实现细节。底层模块只需要实现这个接口便可以与高层模块间接合作。这样当需要更换底层模块时,只需要找另一个实现了这个接口的模块替换即可,而不必再更改高层模块。

装饰模式

装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
当没有用装饰模式时。要为一个类的功能添加某种修饰的时候,可以通过在类中添加方法,字段,逻辑的方式来实现。如果新加入的这些功能在某些条件下才会执行。这就使得需要在类中添加很多的逻辑判断。这无疑使类变得更加复杂。
如果使用装饰模式,就不会有这些顾虑。独立出一个个的装饰类,装饰类中只需要完成相应的装饰逻辑,而不用考虑如何调用。当要对类进行装饰时,只需要调用者按照一定顺序使用装饰类即可;
在这里插入图片描述

例子:

//实现功能的类
public class Animal {
   
    private String  name;
    public Animal(){
   }
    public Animal(String name){
   
        this.name = name;
    }
    public void show(){
   
        System.out.println("的"+name);
    }
}
//装饰类
class Tail extends Body{
   
    @Override
    public void show(){
   
        System.out.print(" 一条长尾巴 ");
        super.show();
    }
}
class Ears extends Body{
   
    @Override
    public void show(){
   
        System.out.print(" 两个大耳朵 ");
        super.show();
    }
}
class Wings extends Body{
   
    @Override
    public void show(){
   
        System.out.print(" 一双翅膀 ");
        super.show();
    }
}
class Eyes extends Body{
   
    @Override
    public void show(){
   
        System.out.print(" 一只眼睛 ");
        super.show();
    }
}
class Nose extends Body{
   
    @Override
    public void show(){
   
        System.out.print(" 一个鼻子 ");
        super.show();
    }
}
//用来扩展Animal的功能
public class Body extends Animal {
   
    Animal animal;

    public void decorate(Animal animal) {
   
        this.animal = animal;
    }

    @Override
    public void show(){
   
        if(animal!=null){
   
            animal.show();
        }
    }
}
public class Test1 {
   
    public static void main(String[] args) {
   
        Animal animal = new Animal("兔子");
        Tail tail = new Tail();
        Ears ears = new Ears();
        Eyes eyes = new Eyes();
        Wings wings = new Wings();


        tail.decorate(animal);
        ears.decorate(tail);
        eyes.decorate(ears);
        wings.decorate(eyes);

        System.out.print("这是一只拥有");
        wings.show();
    }
}

执行结果
在这里插入图片描述

代理模式

代理模式:为其他对象提供一种代理以控制对这个对象的访问。
代理模式可以隔离客户类和业务实现类。在他俩中间加入一层代理。代理模式可以在委托类的方法实现的前后加入一公共的扩展内容。而不必打开委托类。这也符合开闭原则。
在这里插入图片描述

例子

//功能的接口(网购)
public interface OnlineShopping {
   
     public void buyApple();
}
//委托类(顾客)
public class Client implements OnlineShopping{
   
    @Override
    public void buyApple() {
   
        System.out.println("挑选苹果");
    }
}
//代理类
public class Proxy implements OnlineShopping {
   
    Client client;
    @Override
    public void buyApple() {
   
        //真正方法执行前加入一些扩展
        System.out.println("提供网购APP");
        if(client==null){
   
            client = new Client();
        }
        client.buyApple();
        //真正方法执行后加入一些扩展
        System.out.println("将商品送到顾客家中")
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值