设计模式概述

本文介绍了设计模式的概念及其重要性,并详细阐述了开闭原则、里氏代换原则等六大设计原则,同时对设计模式进行了分类。

设计模式(Design pattern)

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

设计原则

为什么要提倡“Design Pattern呢?根本原因是为了代码复用,增加可维护性。那么怎么才能实现代码复用呢?

设计模式的六大原则

  • 开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果,模块应尽量在不修改原(是“原”,指原来的代码)代码的情况下进行扩展。 在面向对象设计中,不允许更改的是系统的抽象层,而允许扩展的是系统的实现层。换言之,定义一个一劳永逸的抽象设计层,允许尽可能多的行为在实现层被实现。

    interface IReader{
        public String getContent();   
    } 
    
    class Newspaper implements IReader {
        public String getContent(){
            eturn "林书豪17+9助尼克斯击败老鹰……"; 
         }
    }
    
    class Book implements IReader{
        public String getContent(){
            return "很久很久以前有一个阿拉伯的故事……";
        }
    } 
    
    class Mother{
        public void narrate(IReader reader){
           System.out.println("妈妈开始讲故事");
           System.out.println(reader.getContent());
        }
    }
    
    public class Client{
        public static void main(String[] args){
            Mother mother = new Mother();
            mother.narrate(new Book());
            mother.narrate(new Newspaper());
        }
    }
    

    这样修改后,无论以后怎样扩展Client类,都不需要再修改Mother类了。

  • 里氏代换原则(Liskov Substitution Principle) 任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。 里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

    如果调用的是父类的话,那么换成子类也完全可以运行。
    IReader reader = new Book();
    System.out.println(reader.getContent());
    
    Book reader = new Book();
    System.out.println(reader.getContent());
    
    
  • 依赖倒转原则(Dependence Inversion Principle) 高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。 抽象不应该依赖于具体实现,具体实现应该依赖于抽象,针对对接口编程,依赖于抽象而不依赖于具体。

    public class HondaCar{
        public void Run(){
            Console.WriteLine("本田开始启动了");
        }
        public void Turn(){
            Console.WriteLine("本田开始转弯了");
        }
        public void Stop(){
            Console.WriteLine("本田开始停车了");
        }
    }
    public class FordCar{
        publicvoidRun(){
            Console.WriteLine("福特开始启动了");
        }
        publicvoidTurn(){
            Console.WriteLine("福特开始转弯了");
        }
        publicvoidStop(){
            Console.WriteLine("福特开始停车了");
        }
    }
    public class AutoSystem{
        public enum CarType{
            Ford,Honda
        };
        private HondaCar hcar=new HondaCar();
        private FordCar fcar=new FordCar();
        private CarType type;
        public AutoSystem(CarType type){
            this.type=type;
        }
        private void RunCar(){
            if(type==CarType.Ford){
                fcar.Run();
            } else {
                hcar.Run();
            }
        }
        private void TurnCar(){
            if(type==CarType.Ford){
                fcar.Turn();
            } else { 
                hcar.Turn();
            }
        }
        private void StopCar(){
            if(type==CarType.Ford){
                fcar.Stop();
                } else {
                    hcar.Stop();
                }
        }
    }
    
    这会给系统增加新的相互依赖。随着时间的推移,越来越多的车种必须加入到AutoSystem中,这个“AutoSystem”模块将会被if/else语句弄得很乱,
    而且依赖于很多的低层模块,只要低层模块发生变动,AutoSystem就必须跟着变动,
    
    public interface ICar
    {
        void Run();
        void Turn();
        void Stop();
    }
    
    public class AutoSystem
    {
        private ICar icar;
        public AutoSystem(ICar icar)
        {
            this.icar=icar;
        }
        private void RunCar()
        {
            icar.Run();
        }
        private void TurnCar()
        {
            icar.Turn();
        }
        private void StopCar()
        {
            icar.Stop();
        }
    }
    现在AutoSystem系统依赖于ICar 这个抽象,而与具体的实现细节HondaCar、FordCar、BmwCar无关,
    所以实现细节的变化不会影响AutoSystem。对于实现细节只要实现ICar 即可,即实现细节依赖于ICar 抽象。
    
  • 接口隔离原则(Interface Segregation Principle) 使用多个专门的接口比使用单一的总接口要好。 一个类对另外一个类的依赖性应当是建立在最小的接口上的。 一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。 不要强迫客户使用它们不用的方法,如果强迫用户使用它们不使用的方法,那么这些客户就会面临由于这些不使用的方法的改变所带来的改变。

    interface IOrderForPortal{
        String getOrder();
    }
    interface IOrderForOtherSys{
        String insertOrder();
        String getOrder();
    }
    interface IOrderForAdmin{ //extendsIOrderForPortal,IOrderForOtherSys
        String deleteOrder();
        String updateOrder();
        String insertOrder();
        String getOrder();
    }
    
    class Order implements IOrderForPortal,IOrderForOtherSys,IOrderForAdmin{
        private Order(){
    
        }
        //返回给Portal
        public static IOrderForPortal getOrderForPortal(){
        return (IOrderForPortal)new Order();
        }
        //返回给OtherSys
        public static IOrderForOtherSys getOrderForOtherSys(){
            return (IOrderForOtherSys)newOrder();
        }
        //返回给Admin
        public static IOrderForAdmin getOrderForAdmin(){
            return (IOrderForAdmin)new Order();
        }
        //--下面是接口方法的实现.只是返回了一个String用于演示
        public String getOrder(){
            return "implemented getOrder";
        }
        public String insertOrder(){
            return "implementedinsertOrder";
        }
        public String updateOrder(){
            return "implementedupdateOrder";
        }
        public String deleteOrder(){
            return "implementeddeleteOrder";
        }
    }
    public class TestCreateLimit{
        public static void main(String[] args){
            IOrderForPortal orderForPortal =Order.getOrderForPortal();
            IOrderForOtherSys orderForOtherSys =Order.getOrderForOtherSys();
            IOrderForAdmin orderForAdmin = Order.getOrderForAdmin();
            System.out.println("Portal门户调用方法:"+orderForPortal.getOrder());
            System.out.println("OtherSys外部系统调用方法:"+orderForOtherSys.insertOrder());
            System.out.println("Admin管理后台调用方法:"+orderForAdmin.getOrder()+";"
                                +orderForAdmin.insertOrder()+";"+orderForAdmin.updateOrder()+";"
                                +orderForAdmin.deleteOrder());
        }
    }
    这样就能很好的满足接口隔离原则了,调用者只能访问它自己的方法,不能访问到不应该访问的方法.
    
  • 迪米特法则(最少知道原则)(Demeter Principle) 一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

  • 合成复用原则(Composite Reuse Principle) 量使用合成/聚合的方式,而不是使用继承。

设计模式的分类

  • 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

转载于:https://my.oschina.net/orgsky/blog/794960

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值