HIT软构博客6-设计模式

设计模式可以分为1.创建型模式 2.结构型模式 3.行为类模式

1.创建型模式

​ 工厂方法模式

​ 当client不知道要创建哪个类的具体实例或不想在客户端代码指明要创建具体哪个子类的实例,用工厂方法。

用户是通过工厂方法得到新的对象,而不是通过new。

HIT软构博客6-设计模式
Product p =new  ConcreteOne().makeObject();

可以简化 在接口中声明静态方法通过类静态方法来构造出不同的对象。

优点:

(1)创建客户所需要的产品,向客户隐藏了哪种具体产品类将被实例化这一细节。
(2)能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。
(3)符合开闭原则–对扩展的开放,对修改已有代码的封闭。
工厂方法模式缺点:
(1)系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销
(2)增加了系统的抽象性和理解难度。

2.Structural patterns

(1)Adater

通过适配器将某个类转成client期望的其他形式

HIT软构博客6-设计模式

客户端要调用Shape接口的display方法,但是这个需求已经被另一个类(LegacyRectangle)实现了,只是不完全匹配,此时就需要一个适配器继承父类或实现接口,让客户端调用适配器,在适配器中display方法,适配了LegacyRectangle中的display方法,从而实际执行LegacyRectangle中的display方法。

interface Shape{
    void display (int x1,int y1,int x2,int y2);
}
class Rectangle implements Shape{
    void display(int x1,int y2,int x2,int y2){
        new LegacyRectangle.display(x1,y1,x2-x1,y2-y1);//适配器,把已有的数据变得符合已有的方法要求。一种delegation,把责任交给别人来实现(LegacyRectangle)。
    }
}
class LegacyRectangle{
    void display(int x1,int y1,int w ,int h){...}//真正的具体实现
}
//客户端要使用的时候,初始化接口的一个具体化对象
class Client{
    Shape shape=new Rectangle();
    public static void main(String[] args){
        shape.display(1,1,2,2);//调用的是适配器,实际实现是在LegacyRectangle。
    }
}
  1. 装饰器模式 避免了组合爆炸和大量的代码重复(如下图)。

HIT软构博客6-设计模式

对每一个要增加的特性构造子类,通过委派机制增加到对象上

HIT软构博客6-设计模式

HIT软构博客6-设计模式

最基础的实现作为基类实现接口。创建一个StackDecorator实现Stack接口,并且派生出不同特殊功能的子类,如LockedStack(具有锁的栈)、UndoStack(可以撤销操作的栈),这些特殊功能由子类自己实现而共性的内容指派给基类实现。

interface Stack{
    void push(Item e);
    Item pop();
}
//基类
public class ArrayStack implements Stack{
    public ArrayStack(){...}
    public void push(Item e){...}
    public Item pop(){...}
}
//Decorator抽象类
public abstract class StackDecorator implements Stack{//也是实现的Stack接口
    protected final Stack stack;//delegate 给基类对象实现基本功能
    public StackDecorator(Stack stack){
        this.stack=stack;
    }
    public void push(Item e){stack.push(e)};//使用基类对象实现基本功能
    public Item pop(){
        return stack.pop();//使用基类对象实现基本功能
    }
}
//具体的一个装饰类继承Decorator抽象类
public class UndoStack extends StackDecorator implements Stack{
    private final UndoLog log=new UndoLog();//实现特性所需要的rep
    public UndoStack(Stack s){super(s);}
    public void push(Item e){log.append(UndoLog.PUSH,e);super.push(e);}
    public void undo(){...}//实现特性
}
//具体使用时要一个具有多个功能的对象
Stack s=new ArrayStack();
Stack=new SecureStack(new SynchronizedStack(new UndoStack(s)));

类似一种套娃和穿衣服

3.Behavior patterns

(1)Strategy

策略模式就是client动态选择不同的算法来完成同一个任务而不是写死在代码里。

为不同的实现算法构造接口,利用delegation,运行时动态传入client想要的算法类的实例。例子:java的sort

HIT软构博客6-设计模式

不同的支付策略不写死在ShoppingCart类中而是delegate给PaymentStrategy接口,它的子类实现不同的支付方法,把子类对象传给ShoppingCart类。

public class ShoppingCart{
    ...

    public void pay(PaymentStrategy ps){
        int amount=calculateTotal();
        ps.pay(amount);//delegate给不同的PaymentStrategy子类来实现支付功能
    }
}
//指派出去的功能的接口
public interface PaymentStrategy{
    public void pay(int amount);
}
//功能的不同实现子类
public class PaypalStrategy implements PaymentStrategy{
    ...

    @override
    public void pay(int amount){...};
}
//client使用的时候
public static void main(String[]args){
    ShoppingCart cart=new ShoppingCart();
    cart.pay(new PaypalStrategy("myacount","pwd"));//用paypal支付
    cart.pay(new CreditCardStrategy("Alice","1234","z"));//用信用卡支付
}

(2)模板模式

做一件事情具有固定的步骤,如第一步通过不同方式拿到一个Poem对象,第二步给日志设置不同的输出目的地,第三步使用不同策略向日志中写入内容。步骤是确定的,但是每一步可以有不同的实现。

共性的步骤在抽象类中实现,差异化步骤在子类中实现

inheritance+override

HIT软构博客6-设计模式
//客户端面对的是OrderProcessTemplate抽象类
public abstract class OrderProcessTemplate{
    protected boolean isGift;
    public final void processOrder(){//做事情的顺序固定住了,不可override。
        doSelect();
        doPayment();
        if(isGift)giftWrap();
        doDelivery();
    }
    public final void giftWrap(){...}//共性的方法直接在抽象类中实现了
    public abstract void doSelect();
    public abstract void doPayment();
    public abstract void processOrder();//差异化步骤留着在子类中实现
}
//子类继承抽象类实现抽象方法
public class NetOrder extends OrderProcessTemplate{
    @override public void doSelect(){...}
    @override public void doPayment(){...}
    @override public void doDelivery(){...}
}
//使用的时候client:
OrderProcessTemplate netOrder=new newOrder();//可以使用工厂静态方法隐藏具体的new操作
netOrder.processOrder();
OrderProcessTemplate storeOrder=new StoreOrder();
storeOrder.processOrder();

缺点是可能会产生组合爆炸

(3)迭代器模式:

让自己的集合类实现Iterable接口,并实现自己的独特Iterator迭代器

public interface Collection extends Iterable{
    ...

    Iterator iterator();//返回一个迭代器
}

例子:

public class Pair implements Iterable{
    private final E first,second;//rep
    ...
    public Iterator iterator(){return new PairIterator();}

    private class PairIterator implements  Iterator{//内部类实现的是Iterator接口,必须override next和hasNext方法
        private boolean seenFirst=false,seenSecond=false;
        public boolean hasNext(){return !seenSecond;}
        public E next(){
            if(!seenFirst){seenFirst=true;return first;}//内部类可以访问到first字段
            if(!seenSecond){seenSecond=true;return second;}
            throw new NoSuchElementException();
        }
        public void remove(){throw new UnsupportedOperationException();}
    }
}

(4)visitor模式

将ADT中的数据和作用于数据的某些特定操作分开

为ADT预留一个将来可以扩展功能的接入点,外部实现的功能代码可以在不改变ADT本身的情况下通过delegation接入ADT

HIT软构博客6-设计模式
//我开发的ADT:
public interface ItemElement{
    public int accept(ShoppingCartVistor vistor);
}
public class Book implements ItemElement{
    private double price;
    public int accept(ShoppingCartVistor vistor){vistor.visit(this);}//接入点,当想用外部的不同功能时传入不同的Vistor功能子类
}
//Vistor接口:
public interface ShoppingCartVistor{
    int visit(Book book){...}
    int visit(Fruit fruit){...}
}
//具体实现
//不同的功能作为不同的vistor接口的子类
//使用时想要不同的外部功能只需要客户端中修改传入的Vistor对象

Original: https://www.cnblogs.com/aurora7301/p/16350048.html
Author: aurora7301
Title: HIT软构博客6-设计模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/684082/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球