0%

代理模式

  代理模式(Proxy),为其他对象提供一种代理以控制这个对象的访问。

代理模式结构图

2.7.1 案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//追求者类
public class Pursuit {
SchoolGirl mm;

public Pursuit(SchoolGirl mm) {
this.mm = mm;
}

public void giveDolls(){
System.out.println(mm.getName() + "送你洋娃娃");
}

public void giveFlowers(){
System.out.println(mm.getName() + "送你鲜花");
}

public void giveChocolate(){
System.out.println(mm.getName() + "送你巧克力");
}
}

//被追求者类
public class SchoolGirl {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

public class Test {
public static void main(String[] args) {
//追求者调用被追求者,增送各种礼物
System.out.println("--------------追求者调用被追求者,增送各种礼物");
SchoolGirl jiaojiao = new SchoolGirl();
jiaojiao.setName("李娇娇");

Pursuit zhuojiayi = new Pursuit(jiaojiao);
zhuojiayi.giveDolls();
zhuojiayi.giveFlowers();
zhuojiayi.giveChocolate();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    public static void main(String[] args) {
//增加代理人
//
System.out.println("--------------增加代理人");
PursuitImpl zhuojiayiNew = new PursuitImpl(jiaojiao);
Proxy daili = new Proxy(zhuojiayiNew);
daili.giveDolls();
daili.giveFlowers();
daili.giveChocolate();
}

//代理接口
public interface IGiveGift {
void giveDolls();
void giveFlowers();
void giveChocolate();
}

public class Proxy implements IGiveGift {
PursuitImpl gg;

public Proxy(PursuitImpl gg) {
this.gg = gg;
}

public void giveDolls(){
gg.giveDolls();
}

public void giveFlowers(){
gg.giveFlowers();
}

public void giveChocolate(){
gg.giveChocolate();
}
}

public class PursuitImpl implements IGiveGift {
SchoolGirl mm;

public PursuitImpl(SchoolGirl mm) {
this.mm = mm;
}

public void giveDolls(){
System.out.println(mm.getName() + "送你洋娃娃");
}

public void giveFlowers(){
System.out.println(mm.getName() + "送你鲜花");
}

public void giveChocolate(){
System.out.println(mm.getName() + "送你巧克力");
}
}

2.7.2 代码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//定义了RealSubject和Proxy的共用接口,这样就可以在使用RealSubject的地方使用Proxy
public abstract class Subject {
public abstract void request();
}

//定义Proxy所代表的真实实体
public class RealSubject extends Subject {
@Override
public void request() {
System.out.println("真实的请求");
}
}

//保存一个引用使得代理可以访问实体,并提供一个与Subject接口相同的接口,使代理可代替实体
public class Proxy extends Subject {
RealSubject realSubject;

@Override
public void request() {
if(realSubject == null){
realSubject = new RealSubject();
}
realSubject.request();
}
}

public class Main {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.request();
}
}

  代理模式

代理模式的应用场景:

  • 远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实,如WebService通过代理来解决远程访问问题。
  • 虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象,以达到性能的优化,比如HTML文件中较大的图片,需要一个个的下载,未打开的图片框就是用虚拟代理代替了真实的图片,此时代理存储了真实图片的路径和尺寸。
  • 安全代理,用来控制真实对象访问时的权限,一般用于对象应该有不同的访问权限的时候。
  • 智能指引,是指当调用真实的对象时,代理处理另外一些事。比如计算真实对象的引用次数,当对象没有引用时就可以自动释放它;或是当第一次引用一个持久对象时,将它装入内存;或在访问一个实际对象前,检查是否已经锁定它,以确保其他对象不能改变它。这些都是通过代理在访问一个对象时附加一些内务处理。

参考:

🔗 《设计模式:可复用面向对象软件的基础》

🔗 《大话设计模式》

享元模式

  享元模式(Flyweight)


参考:

🔗 《设计模式:可复用面向对象软件的基础》

🔗 《大话设计模式》

外观模式

  外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

外观模式结构图

2.5.x 案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

public class Stock1 {
public void sell(){
System.out.println(" 股票1卖出");
}
public void buy(){
System.out.println(" 股票1买入");
}
}

......

public class Realty1 {
public void sell(){
System.out.println(" 不动产1卖出");
}
public void buy(){
System.out.println(" 不动产1买入");
}
}

public class NationalDebt1 {
public void sell(){
System.out.println(" 国债1卖出");
}
public void buy(){
System.out.println(" 国债1买入");
}
}

public class Test {
public static void main(String[] args) {
Stock1 gu1 = new Stock1();
Stock2 gu2 = new Stock2();
Stock3 gu3 = new Stock3();
NationalDebt1 nd1 = new NationalDebt1();
Realty1 rt1 = new Realty1();

gu1.buy();
gu2.buy();
gu3.buy();
nd1.buy();
rt1.buy();

gu1.sell();
gu2.sell();
gu3.sell();
nd1.sell();
rt1.sell();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Fund {
Stock1 gu1;
Stock2 gu2;
Stock3 gu3;
NationalDebt1 nd1;
Realty1 rt1;

public Fund() {
this.gu1 = new Stock1();
this.gu2 = new Stock2();
this.gu3 = new Stock3();
this.nd1 = new NationalDebt1();
this.rt1 = new Realty1();
}

public void buyFund(){
gu1.buy();
gu2.buy();
gu3.buy();
nd1.buy();
rt1.buy();
}

public void sellFund(){
gu1.sell();
gu2.sell();
gu3.sell();
nd1.sell();
rt1.sell();
}
}
public static void main(String[] args) {
//客户不需要一个个股票去了解和买卖,只要购买基金即可,具体买卖由基金公司完成
Fund jijin = new Fund();
jijin.buyFund();
jijin.sellFund();
}

2.5.x 代码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

public class SubSystemOne {
public void methodOne(){
System.out.println(" 子系统方法一");
}
}

public class SubSystemTwo {
public void methodTwo(){
System.out.println(" 子系统方法二");
}
}

public class SubSystemThree {
public void methodThree(){
System.out.println(" 子系统方法三");
}
}

public class SubSystemFour {
public void methodFour(){
System.out.println(" 子系统方法四");
}
}

public class Facade {
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four;

public Facade() {
this.one = new SubSystemOne();
this.two = new SubSystemTwo();
this.three = new SubSystemThree();
this.four = new SubSystemFour();
}

public void methodA(){
System.out.println("\n方法组A() --- ");
one.methodOne();
two.methodTwo();
four.methodFour();
}

public void methodB(){
System.out.println("\n方法组B() --- ");
two.methodTwo();
three.methodThree();
}
}

public class Main {
public static void main(String[] args) {
Facade facade = new Facade();
facade.methodA();
facade.methodB();
}
}

外观模式的使用场景

  三个阶段,首先在设计初期阶段,应该要有意识将不同的两个层分离,如三层架构需要考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。

  其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本应是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。

  第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。此时使用外观模式Facade也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facademic对象交互,Facade与遗留代码交互所有复杂的工作。

外观模式使用场景

  


参考:

🔗 《设计模式:可复用面向对象软件的基础》

🔗 《大话设计模式》

装饰模式

  装饰模式(Decorator),动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。

  • Component,定义了一个对象接口,可以给这些对象动态的添加职责。
  • ConcreteComponent,定义了一个具体的对象,也可以给这个对象添加一些职责。
  • Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,其无需知道Decorator的存在。
  • ConcreteDecorator,就是具体的装饰对象,用来给Component添加各种功能。

装饰模式结构图

2.4.x 案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

public class Test {
public static void main(String[] args) {
//换装系统
Person zs = new Person("张三");
System.out.println("-------------------第一种装扮");
Finery dtx = new TShirtsFinery();
Finery kk = new BigTrouserFinery();
Finery ydx = new SneakerFinery();
dtx.show();
kk.show();
ydx.show();
zs.show();
System.out.println("-------------------第二种装扮");
Finery xz = new SuitFinery();
Finery ld = new TieFinery();
Finery px = new LeatherShoesFinery();
xz.show();
ld.show();
px.show();
zs.show();

//存在问题有:每次都只能单独的穿一件衣服
}
}

//服饰抽象类
public abstract class Finery {
public abstract void show();
}

public class BigTrouserFinery extends Finery {
@Override
public void show() {
System.out.println("垮裤");
}
}

......

public class TShirtsFinery extends Finery {
@Override
public void show() {
System.out.println("大T恤");
}
}

public class Person {
private String name;

public Person() {
}

public Person(String name) {
this.name = name;
}

public void show(){
System.out.println("装扮——" + name);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    public static void main(String[] args) {
//装饰模式
System.out.println("-------------------第一种装扮");
TShirtsDecorator dtxDecorator = new TShirtsDecorator();
BigTrouserDecorator kkDecorator = new BigTrouserDecorator();
SneakerDecorator ydxDecorator = new SneakerDecorator();

dtxDecorator.setComponent(zs);
kkDecorator.setComponent(dtxDecorator);
ydxDecorator.setComponent(kkDecorator);
ydxDecorator.show();

System.out.println("-------------------第二种装扮");
SuitDecorator xzDecorator = new SuitDecorator();
TieDecorator ldDecorator = new TieDecorator();
LeatherShoesDecorator pxDecorator = new LeatherShoesDecorator();

xzDecorator.setComponent(zs);
ldDecorator.setComponent(xzDecorator);
pxDecorator.setComponent(ldDecorator);
pxDecorator.show();
}

public class FineryDecorator extends Person {
protected Person component;

public FineryDecorator() {
}

public void setComponent(Person component) {
this.component = component;
}

@Override
public void show() {
if(component != null){
component.show();
}
}
}

public class BigTrouserDecorator extends FineryDecorator {
@Override
public void show() {
System.out.println("垮裤");
super.show();
}
}

......

public class TShirtsDecorator extends FineryDecorator {
@Override
public void show() {
System.out.println("大T恤");
super.show();
}
}

2.4.x 代码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public abstract class Component {
public abstract void operation();
}

public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("具体对象操作");
}
}

public class ConcreteDecoratorA extends Decorator {
private String addedState;

@Override
public void operation() {
super.operation();//先运行原Component的operation
addedState = "New State";//再执行本类的功能如addedState,相当于对原Component进行了装饰
System.out.println("具体装饰对象A的操作");
}
}

public class ConcreteDecoratorB extends Decorator {

@Override
public void operation() {
super.operation();//先运行原Component的operation
addedBehavior();//再执行本类的功能如addedBehavior(),相当于对原Component进行了装饰
System.out.println("具体装饰对象B的操作");
}

private void addedBehavior(){//本类独有方法,区别于ConcreteDecoratorA
System.out.println("addedBehavior");
}
}

public abstract class Decorator extends Component {
protected Component component;

public void setComponent(Component component) {//设置Component
this.component = component;
}

@Override
public void operation() {//重写operation(),实际执行仍是component.operation()
if(component != null){
component.operation();
}
}
}

public class Main {
public static void main(String[] args) {
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();

//首先用ConcreteComponent实例化对象c,然后用ConcreteDecoratorA实例化对象d1来包装c
d1.setComponent(c);
//再用ConcreteDecoratorB实例化对象d2包装d1
d2.setComponent(d1);
//最终执行d2的operation()
d2.operation();
}
}

  若是只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator就可以是ConcreteComponent的一个子类。同样道理,若只有一个ConcreteDecorator类,那么就没必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

  装饰模式是为已有功能动态的添加更多功能的一种方式。过去当系统需要新功能时,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。这时装饰模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所需要装饰的对象,因此当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序的使用装饰功能包装对象了。

  装饰模式的优点就在于把类中的装饰功能切分出去,这样可以简化原有的类,有效的把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。


参考:

🔗 《设计模式:可复用面向对象软件的基础》
🔗 《大话设计模式》

组合模式

  组合模式(Composite)


参考:

🔗 《设计模式:可复用面向对象软件的基础》
🔗 《大话设计模式》